{"id":712,"date":"2025-02-04T02:56:45","date_gmt":"2025-02-04T02:56:45","guid":{"rendered":"https:\/\/ocr365.com\/?page_id=712"},"modified":"2025-03-16T06:53:26","modified_gmt":"2025-03-16T06:53:26","slug":"gif-ke-teks","status":"publish","type":"page","link":"https:\/\/ocr365.com\/id\/gif-to-text\/","title":{"rendered":"GIF ke Teks"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"712\" class=\"elementor elementor-712\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2349fe04 e-con-full e-flex e-con e-parent\" data-id=\"2349fe04\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d84e9e5 elementor-widget elementor-widget-ucaddon_dual_color_heading\" data-id=\"d84e9e5\" data-element_type=\"widget\" data-widget_type=\"ucaddon_dual_color_heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!-- start Dual Color Heading -->\n\n<div class=\"ue-dual-color-heading\">\n  <h2>\n    <span class=\"ue-title-one\">GIF <\/span> <span class=\"ue-title-two\">to Text<\/span>\n  <\/h2>\n<\/div>\n<!-- end Dual Color Heading -->\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-330004c1 elementor-widget elementor-widget-shortcode\" data-id=\"330004c1\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><!-- Prevent specific elements from being auto-translated -->\n<meta name=\"google\" content=\"notranslate\">\n       \n<div class=\"vision-upload-container\">\n    <form id=\"visionUploadForm\" method=\"post\" enctype=\"multipart\/form-data\">\n        <!-- Initial upload area -->\n        <div class=\"upload-area\" id=\"initialUploadArea\">\n            <div class=\"upload-instructions\">\n                <div class=\"upload-icon\">\n                    <i class=\"fas fa-cloud-arrow-up\"><\/i>\n                <\/div>\n                <h3>Upload Images<\/h3>\n                <p class=\"upload-desc\">Drop Files<\/p>\n            <\/div>\n            \n            <!-- Native file input with custom button -->\n            <div class=\"file-input-wrapper\">\n                <input type=\"file\" \n                       id=\"visionFileInput\" \n                       name=\"files[]\" \n                       accept=\"image\/jpeg,image\/png,image\/gif,image\/bmp,image\/webp,image\/tiff\" \n                       multiple\n                       style=\"opacity: 0; position: absolute; z-index: -1;\">\n                <button type=\"button\" class=\"custom-file-button\">\n                    <i class=\"fas fa-cloud-arrow-up\"><\/i>\n                    <span class=\"button-text\">Select Images<\/span>\n                <\/button>\n            <\/div>\n            <\/div>\n            \n        <!-- Image Gallery View - initially hidden -->\n        <div class=\"vision-gallery-container\" id=\"imageGalleryView\" style=\"display: none;\">\n            <!-- Gallery Header -->\n            <div class=\"gallery-header\">\n                <div class=\"gallery-info\">\n                    <div class=\"image-counter\">\n                        <i class=\"fas fa-images\"><\/i>\n                        <span class=\"images-count\">0<\/span>\n                    <\/div>\n                <\/div>\n                <div class=\"gallery-actions\">\n                    <button type=\"button\" class=\"action-btn add-more-btn\" title=\"Add More Images\">\n                        <i class=\"fas fa-plus\"><\/i><span class=\"btn-text\">Add<\/span>\n                    <\/button>\n                    <div class=\"selection-controls\">\n                        <button type=\"button\" class=\"action-btn delete-selected\" disabled title=\"Delete Selected Images\">\n                            <i class=\"fas fa-trash\"><\/i><span class=\"btn-text\">Delete<\/span>\n                        <\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- Gallery Grid -->\n            <div class=\"gallery-grid view-grid\">\n                <!-- Images will be populated here -->\n        <\/div>\n\n            <!-- Convert button - only shown below image gallery -->\n        <button type=\"submit\" id=\"visionConvertButton\" disabled>\n                <span class=\"dashicons dashicons-text-page\"><\/span>\n            Convert        <\/button>\n        \n        <!-- Daily Limit Warning - hidden by default -->\n        <div id=\"visionDailyLimitWarning\" class=\"vision-daily-limit-warning\" style=\"display: none;\">\n            <div class=\"limit-warning-content\">\n                <button type=\"button\" class=\"limit-close-btn\" onclick=\"document.getElementById('visionDailyLimitWarning').style.display='none';\">\u00d7<\/button>\n                <div class=\"limit-icon\">\n                    <span class=\"dashicons dashicons-warning\"><\/span>\n                <\/div>\n                <div class=\"limit-message\">\n                    <p class=\"limit-main-text\">You have reached your daily limit of <span class=\"limit-count\">5<\/span> free conversions<\/p>\n                    <p class=\"limit-reset-text\">\n                        Please try again tomorrow or <a href=\"https:\/\/ocr365.com\/id\/pricing\/\" class=\"inline-upgrade-link\" data-no-translation>upgrade<\/a> for unlimited conversions                    <\/p>\n                    <div class=\"limit-countdown\" id=\"limitCountdown\">\n                        <span class=\"limit-countdown-label\">Resets in:<\/span>\n                        <span class=\"limit-countdown-time\" id=\"limitCountdownTime\">--:--:--<\/span>\n                    <\/div>\n                <\/div>\n                <div class=\"limit-actions\">\n                    <a href=\"https:\/\/ocr365.com\/id\/pricing\/\" class=\"limit-upgrade-btn\" data-no-translation>\n                        Upgrade Now                    <\/a>\n                <\/div>\n            <\/div>\n        <\/div>\n        \n        <!-- Cloudflare Turnstile Container - only shown for non-subscribers -->\n                <div id=\"visionTurnstileContainer\" class=\"turnstile-container\" style=\"display: none; margin: 20px auto; text-align: center;\">\n            <!-- Turnstile widget will be rendered here -->\n        <\/div>\n                <\/div>\n\n        <!-- Progress Container -->\n        <div id=\"visionProgressContainer\" class=\"vision-progress-container\" style=\"display: none;\">\n            <div class=\"vision-progress-message\">\n                <div class=\"vision-progress-icon\">\n                    <span class=\"dashicons dashicons-update\"><\/span>\n                <\/div>\n                <div class=\"vision-progress-text\">Processing your images...<\/div>\n            <\/div>\n            <div class=\"vision-progress-status\">\n                <div class=\"vision-progress-bar\"><\/div>\n            <\/div>\n        <\/div>\n\n        <!-- Results Container -->\n        <div id=\"visionResults\"><\/div>\n\n        <!-- Error Messages -->\n        <div id=\"visionErrorMessages\" class=\"error-message\" style=\"display: none;\"><\/div>\n    <\/form>\n<\/div>\n\n<!-- Image Preview Modal -->\n<div class=\"vision-image-preview-modal\">\n    <div class=\"modal-overlay\"><\/div>\n    <div class=\"modal-content\">\n        <button class=\"modal-close\"><i class=\"fas fa-times\"><\/i><\/button>\n        <div class=\"preview-navigation\">\n            <button class=\"nav-btn prev-image\"><i class=\"fas fa-chevron-left\"><\/i><\/button>\n            <div class=\"preview-image-container\">\n                <img decoding=\"async\" src=\"\" alt=\"Preview\" class=\"preview-image\">\n            <\/div>\n            <button class=\"nav-btn next-image\"><i class=\"fas fa-chevron-right\"><\/i><\/button>\n        <\/div>\n        <div class=\"preview-info\">\n            <h3 class=\"preview-filename\"><\/h3>\n            <div class=\"preview-metadata\">\n                <span class=\"preview-size\"><\/span>\n                <span class=\"preview-dimensions\"><\/span>\n                <span class=\"preview-type\"><\/span>\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<!-- Modal window for limit notification -->\n<div id=\"visionLimitModal\" class=\"vision-limit-modal\">\n    <div class=\"vision-limit-content\">\n        <div class=\"vision-limit-close\" id=\"limitModalCloseBtn\">\u00d7<\/div>\n        \n        <div class=\"vision-limit-header\">\n            <div class=\"limit-icon\">\n                <span class=\"dashicons dashicons-lock\"><\/span>\n            <\/div>\n            <h3>Batch Upload Limit<\/h3>\n            <p>You have reached the batch upload limit for free users<\/p>\n        <\/div>\n\n        <div class=\"vision-limit-plan\">\n            <div class=\"plan-badge\">Pro<\/div>\n            <ul class=\"vision-limit-features\">\n                <li>\n                    Larger batch upload limits\n                <\/li>\n                <li>\n                    Unlimited daily conversions\n                <\/li>\n                <li>\n                    Priority processing\n                <\/li>\n            <\/ul>\n        <\/div>\n\n        <div class=\"vision-limit-actions\">\n            <a href=\"https:\/\/ocr365.com\/id\/pricing\/\" \n               class=\"vision-upgrade-button\" data-no-translation>\n                Upgrade to Pro\n            <\/a>\n        <\/div>\n    <\/div>\n<\/div>\n\n<script>\n\/\/ Wait for DOM to be fully loaded\ndocument.addEventListener('DOMContentLoaded', function() {\n    \/\/ Get the close button element\n    var closeBtn = document.getElementById('limitModalCloseBtn');\n    if (closeBtn) {\n        \/\/ Add click event listener\n        closeBtn.addEventListener('click', function() {\n            \/\/ Check if global closeModal function exists\n            if (typeof closeModal === 'function') {\n                closeModal();\n            } else {\n                \/\/ If function doesn't exist, hide modal directly\n                var modal = document.getElementById('visionLimitModal');\n                if (modal) {\n                    modal.style.display = 'none';\n                    document.body.style.overflow = '';\n                }\n            }\n        });\n    }\n});\n<\/script> \n<!-- Add required libraries -->\n<link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.4.0\/css\/all.min.css\">\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jszip\/3.10.1\/jszip.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/FileSaver.js\/2.0.5\/FileSaver.min.js\"><\/script>\n\n<script>\n\/\/ Define a simple and effective returnToUpload function\nwindow.returnToUpload = function(event) {\n    if (event) event.preventDefault();\n    \n    \/\/ Show upload area\n    document.getElementById('initialUploadArea').style.display = 'block';\n    document.getElementById('visionResults').style.display = 'none';\n    \n    \/\/ Remove body class when results are hidden\n    document.body.classList.remove('vision-results-active');\n    \n    \/\/ Clear results container\n    document.getElementById('visionResults').innerHTML = '';\n    \n    return false;\n};\n\ndocument.addEventListener('DOMContentLoaded', function() {\n    var fileInput = document.getElementById('visionFileInput');\n    var customButton = document.querySelector('.custom-file-button .button-text');\n    var convertButton = document.getElementById('visionConvertButton');\n    var selectedFilesMap = new Map();\n    var initialUploadArea = document.getElementById('initialUploadArea');\n    var imageGalleryView = document.getElementById('imageGalleryView');\n    var galleryGrid = document.querySelector('.gallery-grid');\n    var previewModal = document.querySelector('.vision-image-preview-modal');\n    var turnstileContainer = document.getElementById('visionTurnstileContainer');\n    var turnstileToken = '';\n    var turnstileWidgetId = null;\n    let currentImageIndex = 0;\n    let galleryItems = [];\n    let isSubmitting = false; \/\/ Add submission status flag\n    \n    \/\/ Output debug information to verify wpVision object is correctly loaded\n    console.log('VisionPlugin initialization - Batch upload limits:', {\n        wpVision: typeof wpVision !== 'undefined' ? {\n            maxFiles: wpVision.maxFiles,\n            subscriptionType: wpVision.subscriptionType\n        } : 'undefined',\n        maxBatchLimit: typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n            (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 'undefined'\n    });\n    \n    \/\/ Ensure progress container is hidden on page load\n    const progressContainer = document.getElementById('visionProgressContainer');\n    if (progressContainer) {\n        progressContainer.style.display = 'none';\n    }\n    \n    \/\/ Initialize drag and drop functionality\n    initializeDragDrop();\n    \n    function initializeDragDrop() {\n        if (!initialUploadArea) return;\n        \n        \/\/ Add event listeners for drag and drop area\n        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\n            initialUploadArea.addEventListener(eventName, preventDefaults, false);\n        });\n        \n        \/\/ Add drag effects\n        initialUploadArea.addEventListener('dragenter', highlight, false);\n        initialUploadArea.addEventListener('dragover', highlight, false);\n        initialUploadArea.addEventListener('dragleave', unhighlight, false);\n        initialUploadArea.addEventListener('drop', unhighlight, false);\n        \n        \/\/ Handle file drop\n        initialUploadArea.addEventListener('drop', handleDrop, false);\n        \n        function preventDefaults(e) {\n            e.preventDefault();\n            e.stopPropagation();\n        }\n        \n        function highlight() {\n            initialUploadArea.classList.add('highlight');\n        }\n        \n        function unhighlight() {\n            initialUploadArea.classList.remove('highlight');\n        }\n        \n        function handleDrop(e) {\n            const dt = e.dataTransfer;\n            const files = dt.files;\n            \n            \/\/ Directly use the same logic as click upload\n            if (files && files.length > 0) {\n                \/\/ Set dropped files to the file input element to trigger the same handling as click upload\n                try {\n                    \/\/ Create a DataTransfer object\n                    const dataTransfer = new DataTransfer();\n                    \n                    \/\/ Add all dropped files\n                    Array.from(files).forEach(file => {\n                        dataTransfer.items.add(file);\n                    });\n                    \n                    \/\/ Set to file input element\n                    fileInput.files = dataTransfer.files;\n                    \n                    \/\/ Manually trigger change event to execute the same logic as click upload\n                    const event = new Event('change', { bubbles: true });\n                    fileInput.dispatchEvent(event);\n                } catch (error) {\n                    console.error('Error setting files:', error);\n                    \/\/ If file setting fails, show an error\n                    showError('Error processing files, please try selecting files using the upload button.');\n                }\n            }\n        }\n    }\n    \n    if (fileInput && customButton) {\n        fileInput.addEventListener('change', function() {\n            \/\/ Check file limits before adding files\n            const newFiles = Array.from(this.files);\n            \n            \/\/ Check and filter duplicate files\n            const uniqueFiles = filterDuplicateFiles(newFiles);\n            \n            \/\/ If all files are duplicates, notify the user\n            if (uniqueFiles.length === 0 && newFiles.length > 0) {\n                showError('Duplicate files detected', 'warning');\n                return;\n            }\n            \n            \/\/ Use the same checking method as handleFiles function\n            \/\/ Check file limits with auto-trimming enabled\n            if (!checkFileLimits(uniqueFiles, true)) return;\n            \n            \/\/ Get the limited files if needed\n            const limitedFiles = getLimitedFiles(uniqueFiles);\n            if (limitedFiles.length === 0) return;\n            \n            \/\/ Store allowed files\n            limitedFiles.forEach((file, index) => {\n                const fileId = 'file_' + Date.now() + '_' + index;\n                selectedFilesMap.set(fileId, file);\n            });\n            \n            updateButtonText();\n            updateGalleryInfo();\n            showGalleryView();\n            renderGalleryItems();\n        });\n\n        \/\/ Function to check for duplicate files\n        function filterDuplicateFiles(newFiles) {\n            const uniqueFiles = [];\n            \n            newFiles.forEach(newFile => {\n                let isDuplicate = false;\n                \n                \/\/ Check existing files for duplicates\n                selectedFilesMap.forEach(existingFile => {\n                    \/\/ Determine if files are identical by name and size\n                    if (existingFile.name === newFile.name && existingFile.size === newFile.size) {\n                        isDuplicate = true;\n                    }\n                });\n                \n                \/\/ If not a duplicate, add to unique files list\n                if (!isDuplicate) {\n                    uniqueFiles.push(newFile);\n                }\n            });\n            \n            return uniqueFiles;\n        }\n\n        \/\/ Trigger file input when custom button is clicked\n        document.querySelector('.custom-file-button').addEventListener('click', function() {\n            fileInput.click();\n        });\n        \n        \/\/ Add more images button\n        document.querySelector('.add-more-btn').addEventListener('click', function() {\n            \/\/ Create a new file input element\n            const newFileInput = document.createElement('input');\n            newFileInput.type = 'file';\n            newFileInput.multiple = true;\n            newFileInput.accept = 'image\/jpeg,image\/png,image\/gif,image\/bmp,image\/webp,image\/tiff';\n            \n            \/\/ Listen for change event on new file input\n            newFileInput.addEventListener('change', function(e) {\n                \/\/ Get newly selected files\n                const newFiles = Array.from(this.files);\n                \n                \/\/ Use the same duplicate file filter function\n                const uniqueFiles = filterDuplicateFiles(newFiles);\n                \n                \/\/ If all files are duplicates, show a warning\n                if (uniqueFiles.length === 0 && newFiles.length > 0) {\n                    showError('Duplicate files detected', 'warning');\n                    document.body.removeChild(newFileInput); \/\/ Remove temporary element\n                    return;\n                }\n                \n                \/\/ Calculate current files count and max files limit\n                const currentCount = selectedFilesMap.size;\n                const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                    (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n                \n                \/\/ First check file limits without auto-trimming to show modal\n                if (currentCount + uniqueFiles.length > maxFiles) {\n                    checkFileLimits(uniqueFiles, false);\n                }\n                \n                \/\/ Now check with auto-trimming to process files\n                if (!checkFileLimits(uniqueFiles, true)) {\n                    document.body.removeChild(newFileInput); \/\/ Remove temporary element\n                    return;\n                }\n                \n                \/\/ Get the limited files if needed\n                const limitedFiles = getLimitedFiles(uniqueFiles);\n                if (limitedFiles.length === 0) {\n                    document.body.removeChild(newFileInput); \/\/ Remove temporary element\n                    return;\n                }\n                \n                \/\/ Store allowed files\n                limitedFiles.forEach((file, index) => {\n                    const fileId = 'file_' + Date.now() + '_' + index;\n                    selectedFilesMap.set(fileId, file);\n                });\n                \n                updateButtonText();\n                updateGalleryInfo();\n                showGalleryView();\n                renderGalleryItems();\n                \n                \/\/ Remove the temporary file input element\n                document.body.removeChild(newFileInput);\n            });\n            \n            \/\/ Append new file input to body and trigger click\n            document.body.appendChild(newFileInput);\n            newFileInput.style.display = 'none';\n            newFileInput.click();\n        });\n        \n        \/\/ Delete selected button\n        document.querySelector('.delete-selected').addEventListener('click', function() {\n            const selectedCheckboxes = document.querySelectorAll('.gallery-item-checkbox:checked');\n            selectedCheckboxes.forEach(checkbox => {\n                const galleryItem = checkbox.closest('.gallery-item');\n                if (galleryItem) {\n                    const fileId = galleryItem.getAttribute('data-file-id');\n                    selectedFilesMap.delete(fileId);\n                    galleryItem.remove();\n                }\n            });\n            \n            updateGalleryInfo();\n            updateButtonText();\n            updateDeleteSelectedButton();\n            \n            \/\/ If no images left, return to initial upload view\n            if (selectedFilesMap.size === 0) {\n                showInitialUploadArea();\n            }\n        });\n        \n        \/\/ Handle gallery item events (preview and delete)\n        galleryGrid.addEventListener('click', function(e) {\n            \/\/ Handle preview action\n            if (e.target.closest('.preview-action')) {\n                const galleryItem = e.target.closest('.gallery-item');\n                openPreviewModal(galleryItem);\n            }\n            \n            \/\/ Handle delete action\n            if (e.target.closest('.delete-action')) {\n                const galleryItem = e.target.closest('.gallery-item');\n                const fileId = galleryItem.getAttribute('data-file-id');\n                selectedFilesMap.delete(fileId);\n                galleryItem.remove();\n                \n                updateGalleryInfo();\n                updateButtonText();\n                \n                \/\/ Update gallery items array\n                galleryItems = Array.from(document.querySelectorAll('.gallery-item'));\n                \n                \/\/ If no images left, return to initial upload view\n                if (selectedFilesMap.size === 0) {\n                    showInitialUploadArea();\n                }\n            }\n        });\n        \n        \/\/ Image preview modal handlers\n        document.querySelector('.modal-close').addEventListener('click', closePreviewModal);\n        document.querySelector('.modal-overlay').addEventListener('click', function(e) {\n            if (e.target === this) {\n                closePreviewModal();\n            }\n        });\n        \n        \/\/ Navigation in preview modal\n        document.querySelector('.prev-image').addEventListener('click', function() {\n            if (currentImageIndex > 0) {\n                currentImageIndex--;\n                updatePreviewImage();\n            }\n        });\n        \n        document.querySelector('.next-image').addEventListener('click', function() {\n            if (currentImageIndex < galleryItems.length - 1) {\n                currentImageIndex++;\n                updatePreviewImage();\n            }\n        });\n\n        \/\/ Function to update button text and file input state\n        function updateButtonText() {\n            const filesCount = selectedFilesMap.size;\n            customButton.textContent = filesCount > 0 ? \n                'Images Selected' : \n                'Select Images';\n            \n            \/\/ Show\/hide convert button based on file count\n            if (filesCount > 0) {\n                convertButton.classList.add('show');\n                convertButton.disabled = false;\n            } else {\n                convertButton.classList.remove('show');\n                convertButton.disabled = true;\n            }\n\n            \/\/ Sync the native file input with selected files\n            const dataTransfer = new DataTransfer();\n            selectedFilesMap.forEach(file => {\n                dataTransfer.items.add(file);\n            });\n            fileInput.files = dataTransfer.files;\n        }\n\n        \/\/ Function to show gallery view\n        function showGalleryView() {\n            if (initialUploadArea && imageGalleryView) {\n                initialUploadArea.style.display = 'none';\n                imageGalleryView.style.display = 'flex';\n            }\n        }\n        \n        \/\/ Function to show initial upload area\n        function showInitialUploadArea() {\n            if (initialUploadArea && imageGalleryView) {\n                initialUploadArea.style.display = 'block';\n                imageGalleryView.style.display = 'none';\n            }\n        }\n        \n        \/\/ Update gallery info (count, etc)\n        function updateGalleryInfo() {\n            const count = selectedFilesMap.size;\n            document.querySelector('.images-count').textContent = count;\n            \n            \/\/ Update convert button state\n            if (convertButton) {\n                convertButton.disabled = count === 0;\n                convertButton.classList.toggle('show', count > 0);\n            }\n            \n            \/\/ Update delete selected button state\n            updateDeleteSelectedButton();\n        }\n        \n        \/\/ Render all gallery items\n        function renderGalleryItems() {\n            \/\/ Clear current gallery\n            galleryGrid.innerHTML = '';\n            galleryItems = [];\n            \n            \/\/ Add each file to the gallery\n            selectedFilesMap.forEach((file, fileId) => {\n                createGalleryItem(file, fileId);\n            });\n            \n            \/\/ Update gallery info after rendering\n            updateGalleryInfo();\n        }\n        \n        \/\/ Create a single gallery item\n        function createGalleryItem(file, fileId) {\n            const reader = new FileReader();\n            const galleryItem = document.createElement('div');\n            galleryItem.className = 'gallery-item';\n            galleryItem.setAttribute('data-file-id', fileId);\n            \n            reader.onload = function(e) {\n                \/\/ Create image element to get dimensions\n                const img = new Image();\n                img.onload = function() {\n                    const dimensions = `${this.width} \u00d7 ${this.height}`;\n                    \n                    \/\/ Update item HTML\n                    galleryItem.innerHTML = `\n                        <div class=\"item-checkbox\">\n                            <input type=\"checkbox\" class=\"gallery-item-checkbox\">\n                        <\/div>\n                        <div class=\"item-preview\">\n                            <img decoding=\"async\" src=\"${e.target.result}\" alt=\"${file.name}\">\n                            <div class=\"item-overlay\">\n                                <button type=\"button\" class=\"item-action preview-action\"><i class=\"fas fa-search-plus\"><\/i><\/button>\n                                <button type=\"button\" class=\"item-action delete-action\"><i class=\"fas fa-trash\"><\/i><\/button>\n                            <\/div>\n                        <\/div>\n                        <div class=\"item-info\">\n                            <h4 class=\"item-name\" title=\"${file.name}\">${file.name}<\/h4>\n                            <span class=\"item-meta\">${formatFileSize(file.size)} \u00b7 ${dimensions}<\/span>\n                        <\/div>\n                    `;\n                    \n                    \/\/ Add event listeners for checkbox\n                    const checkbox = galleryItem.querySelector('.gallery-item-checkbox');\n                    checkbox.addEventListener('change', function() {\n                        updateDeleteSelectedButton();\n                    });\n                    \n                    \/\/ Update gallery items array\n                    galleryItems = Array.from(document.querySelectorAll('.gallery-item'));\n                };\n                img.src = e.target.result;\n            };\n            \n            reader.onerror = function() {\n                console.error(\"Error reading file:\", file.name);\n            };\n            \n            reader.readAsDataURL(file);\n            galleryGrid.appendChild(galleryItem);\n        }\n        \n        \/\/ Format file size for display\n        function formatFileSize(bytes) {\n            if (bytes === 0) return '0 Bytes';\n            const k = 1024;\n            const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n            const i = Math.floor(Math.log(bytes) \/ Math.log(k));\n            return parseFloat((bytes \/ Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n        }\n        \n        \/\/ Open preview modal\n        function openPreviewModal(galleryItem) {\n            galleryItems = Array.from(document.querySelectorAll('.gallery-item'));\n            currentImageIndex = galleryItems.indexOf(galleryItem);\n            \n            updatePreviewImage();\n            previewModal.classList.add('open');\n            document.body.style.overflow = 'hidden'; \/\/ Prevent background scrolling\n        }\n        \n        \/\/ Close preview modal\n        function closePreviewModal() {\n            previewModal.classList.remove('open');\n            document.body.style.overflow = '';\n        }\n        \n        \/\/ Update preview image and navigation\n        function updatePreviewImage() {\n            const galleryItem = galleryItems[currentImageIndex];\n            const fileId = galleryItem.getAttribute('data-file-id');\n            const file = selectedFilesMap.get(fileId);\n            const img = galleryItem.querySelector('.item-preview img');\n            const name = galleryItem.querySelector('.item-name').textContent;\n            const metaText = galleryItem.querySelector('.item-meta').textContent;\n            \n            \/\/ Update modal content\n            document.querySelector('.preview-image').src = img.src;\n            document.querySelector('.preview-filename').textContent = name;\n            \n            \/\/ Parse metadata\n            const sizeMatch = metaText.match(\/([0-9.]+\\s+[A-Z]+)\/);\n            const dimensionsMatch = metaText.match(\/([0-9]+\\s+\u00d7\\s+[0-9]+)\/);\n            \n            if (sizeMatch) document.querySelector('.preview-size').textContent = sizeMatch[0];\n            if (dimensionsMatch) document.querySelector('.preview-dimensions').textContent = dimensionsMatch[0];\n            document.querySelector('.preview-type').textContent = file.type.split('\/')[1].toUpperCase();\n            \n            \/\/ Update navigation buttons\n            document.querySelector('.prev-image').disabled = currentImageIndex === 0;\n            document.querySelector('.next-image').disabled = currentImageIndex === galleryItems.length - 1;\n        }\n        \n        \/\/ Update delete selected button state\n        function updateDeleteSelectedButton() {\n            const selectedCount = document.querySelectorAll('.gallery-item-checkbox:checked').length;\n            document.querySelector('.delete-selected').disabled = selectedCount === 0;\n        }\n\n        \/\/ Keyboard navigation for preview modal\n        document.addEventListener('keydown', function(e) {\n            if (!previewModal.classList.contains('open')) return;\n            \n            switch(e.key) {\n                case 'Escape':\n                    closePreviewModal();\n                    break;\n                case 'ArrowLeft':\n                    if (currentImageIndex > 0) {\n                        currentImageIndex--;\n                        updatePreviewImage();\n                    }\n                    break;\n                case 'ArrowRight':\n                    if (currentImageIndex < galleryItems.length - 1) {\n                        currentImageIndex++;\n                        updatePreviewImage();\n                    }\n                    break;\n            }\n        });\n\n        \/\/ Update file handling function\n        function handleFiles(files) {\n            if (!files.length) return;\n            \n            \/\/ Filter files for valid types first\n            const validFiles = Array.from(files).filter(file => {\n                \/\/ Define allowed MIME types\n                const allowedTypes = [\n                    'image\/jpeg',\n                    'image\/png',\n                    'image\/gif',\n                    'image\/bmp',\n                    'image\/webp',\n                    'image\/tiff'\n                ];\n                \n                const isValid = allowedTypes.includes(file.type);\n                \n                if (!isValid) {\n                    showError(`${file.name} is not a supported image format. Supported formats: JPEG, PNG, GIF, BMP, WebP, TIFF`);\n                }\n                \n                return isValid;\n            });\n            \n            \/\/ Calculate current files count and max files limit\n            const currentCount = selectedFilesMap.size;\n            const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n            \n            \/\/ First check file limits without auto-trimming to show modal\n            if (currentCount + validFiles.length > maxFiles) {\n                checkFileLimits(validFiles, false);\n            }\n            \n            \/\/ Now check with auto-trimming to process files\n            if (!checkFileLimits(validFiles, true)) return;\n            \n            \/\/ Get the limited files if needed\n            const limitedFiles = getLimitedFiles(validFiles);\n            if (limitedFiles.length === 0) return;\n            \n            \/\/ Process each file\n            limitedFiles.forEach(file => {\n                const fileId = 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);\n                selectedFilesMap.set(fileId, file);\n                createFilePreview(file, fileId);\n            });\n            \n            \/\/ Update UI\n            updateButtonText();\n            showGalleryView();\n            renderGalleryItems();\n        }\n\n        \/\/ Add function to check file limits\n        function checkFileLimits(files, shouldTrim = false) {\n            const currentCount = selectedFilesMap.size;\n            const newCount = files.length;\n            const totalCount = currentCount + newCount;\n            \n            \/\/ Get maximum file limit\n            const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n            \n            \/\/ Add detailed debug logs\n            console.log('Checking batch upload limits:', {\n                currentFilesCount: currentCount,\n                newFilesCount: newCount, \n                totalFilesCount: totalCount,\n                maxLimit: maxFiles,\n                subscriptionType: wpVision.subscriptionType,\n                shouldTrim: shouldTrim,\n                exceedsLimit: totalCount > maxFiles\n            });\n            \n            if (totalCount > maxFiles) {\n                \/\/ If not in trim mode, just show the modal and return false\n                if (!shouldTrim) {\n                    const limitModal = document.getElementById('visionLimitModal');\n                    if (limitModal) {\n                        limitModal.style.display = 'flex';\n                        document.body.style.overflow = 'hidden';\n                    } else {\n                        alert(`You can upload a maximum of ${maxFiles} images at once. Please remove some images and try again.`);\n                    }\n                    return false;\n                }\n                \n                \/\/ Calculate how many more files we can add\n                const remainingSlots = Math.max(0, maxFiles - currentCount);\n                \n                \/\/ If we can't add any more files\n                if (remainingSlots <= 0) {\n                    const limitModal = document.getElementById('visionLimitModal');\n                    if (limitModal) {\n                        limitModal.style.display = 'flex';\n                        document.body.style.overflow = 'hidden';\n                    }\n                    return false;\n                }\n                \n                \/\/ Always show the modal when exceeding limits, even in trim mode\n                const limitModal = document.getElementById('visionLimitModal');\n                if (limitModal) {\n                    limitModal.style.display = 'flex';\n                    document.body.style.overflow = 'hidden';\n                }\n                \n                \/\/ Return true since we'll process some files\n                return true;\n            }\n            \n            return true;\n        }\n        \n        \/\/ Function to get limited files according to subscription limits\n        function getLimitedFiles(files) {\n            const currentCount = selectedFilesMap.size;\n            \n            \/\/ Get maximum file limit\n            const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n                \n            if (currentCount + files.length > maxFiles) {\n                \/\/ Calculate how many more files we can add\n                const remainingSlots = Math.max(0, maxFiles - currentCount);\n                \n                \/\/ If we can't add any more files\n                if (remainingSlots <= 0) {\n                    return [];\n                }\n                \n                \/\/ Return only the allowed number of files\n                return files.slice(0, remainingSlots);\n            }\n            \n            \/\/ If within limits, return all files\n            return files;\n        }\n\n        \/\/ Add function to show errors\n        function showError(message, type = 'error', duration = 3000) {\n            \/\/ Create or get toast notification element\n            let toastElement = document.querySelector('.vision-notification-toast');\n            if (!toastElement) {\n                toastElement = document.createElement('div');\n                toastElement.className = 'vision-notification-toast';\n                document.body.appendChild(toastElement);\n            }\n            \n            \/\/ Set notification type style\n            toastElement.className = `vision-notification-toast ${type}`;\n            \n            \/\/ Set notification content\n            toastElement.innerHTML = `\n                <div class=\"toast-icon\">\n                    ${type === 'error' ? '<i class=\"fas fa-exclamation-circle\"><\/i>' : \n                      type === 'warning' ? '<i class=\"fas fa-exclamation-triangle\"><\/i>' : \n                      '<i class=\"fas fa-info-circle\"><\/i>'}\n                <\/div>\n                <div class=\"toast-message\">${message}<\/div>\n            `;\n            \n            \/\/ Show notification\n            toastElement.classList.add('show');\n            \n            \/\/ Set auto-hide\n            setTimeout(() => {\n                toastElement.classList.remove('show');\n            }, duration);\n        }\n\n        \/\/ Add form submission event listener\n        document.getElementById('visionUploadForm').addEventListener('submit', function(e) {\n            e.preventDefault();\n            \n            \/\/ Prevent multiple submissions\n            if (isSubmitting) {\n                console.log('Form is already being submitted');\n                return;\n            }\n            \n            \/\/ Make sure results container is empty and hidden initially\n            const resultsContainer = document.getElementById('visionResults');\n            if (resultsContainer) {\n                resultsContainer.innerHTML = '';\n                resultsContainer.style.display = 'none';\n            }\n            \n            \/\/ Check if user is a subscriber\n            const isSubscriber = wpVision.isSubscriber;\n            \n            \/\/ If Turnstile is enabled and user is not a subscriber\n            if (wpVision.turnstile.enabled && !isSubscriber) {\n                \/\/ If Turnstile token is not yet obtained, show the Turnstile widget\n                if (!turnstileToken) {\n                    \/\/ Show Turnstile container\n                    if (turnstileContainer) {\n                        turnstileContainer.style.display = 'block';\n                    }\n                    \n                    \/\/ Scroll to Turnstile container\n                    if (turnstileContainer) {\n                        turnstileContainer.scrollIntoView({ behavior: 'smooth', block: 'center' });\n                    }\n                    \n                    \/\/ Render Turnstile widget if not already rendered\n                    if (!turnstileWidgetId && turnstileContainer) {\n                        turnstileWidgetId = turnstile.render('#visionTurnstileContainer', {\n                            sitekey: wpVision.turnstile.siteKey,\n                            callback: function(token) {\n                                console.log('Turnstile verification successful');\n                                \/\/ Store token\n                                turnstileToken = token;\n                                \n                                \/\/ Hide Turnstile container\n                                if (turnstileContainer) {\n                                    turnstileContainer.style.display = 'none';\n                                }\n                                \n                                \/\/ Now start the actual form submission process\n                                startFormSubmission();\n                            },\n                            'expired-callback': function() {\n                                \/\/ Reset token\n                                turnstileToken = '';\n                                turnstileWidgetId = null;\n                            }\n                        });\n                    }\n                    \n                    return;\n                }\n            }\n            \n            \/\/ If we reach here, either user is a subscriber or Turnstile verification is complete\n            startFormSubmission();\n        });\n        \n        \/\/ Override the global showProgress function to prevent it from being called elsewhere\n        window.showProgress = function() {\n            console.log('Global showProgress called but ignored');\n            \/\/ Do nothing - we'll control progress display ourselves\n        };\n        \n        \/\/ Function to start the form submission process\n        function startFormSubmission() {\n            console.log('Starting form submission process');\n            isSubmitting = true;\n            \n            \/\/ Hide image gallery and initial upload area\n            if (imageGalleryView) {\n                imageGalleryView.style.display = 'none';\n            }\n            \n            if (initialUploadArea) {\n                initialUploadArea.style.display = 'none';\n            }\n            \n            \/\/ Show loading state on button\n            if (convertButton) {\n                convertButton.disabled = true;\n                convertButton.innerHTML = '<span class=\"dashicons dashicons-update rotating\"><\/span> Converting...';\n            }\n            \n            \/\/ Now show results container with progress animation\n            const resultsContainer = document.getElementById('visionResults');\n            if (resultsContainer) {\n                resultsContainer.style.display = 'block';\n                \n                \/\/ Create animated progress indicator\n                const progressHtml = `\n                    <div class=\"vision-animated-loader\">\n                        <div class=\"loader-pulse\">\n                            <div class=\"loader-track\"><\/div>\n                            <div class=\"loader-progress\"><\/div>\n                            <div class=\"loader-circle\"><\/div>\n                            <div class=\"loader-particles\">\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                            <\/div>\n                            <div class=\"loader-complete\"><\/div>\n                        <\/div>\n                    <\/div>\n                `;\n                \n                resultsContainer.innerHTML = progressHtml;\n            }\n            \n            \/\/ Now proceed with the actual AJAX submission\n            submitFormData();\n        }\n        \n        \/\/ Function to submit the form data via AJAX\n        async function submitFormData() {\n            try {\n                \/\/ Create FormData object\n                const formData = new FormData();\n                \n                \/\/ Add all selected files\n                selectedFilesMap.forEach((file, fileId) => {\n                    formData.append('files[]', file);\n                });\n                \n                \/\/ Add other necessary data\n                formData.append('action', 'vision_convert_images');\n                formData.append('nonce', wpVision.nonce);\n                \n                \/\/ Add Turnstile token if available\n                if (turnstileToken) {\n                    formData.append('turnstile_token', turnstileToken);\n                }\n                \n                console.log('Sending AJAX request');\n                \/\/ Send a single AJAX request\n                const response = await fetch(wpVision.ajaxurl, {\n                    method: 'POST',\n                    body: formData,\n                    credentials: 'same-origin'\n                });\n\n                const data = await response.json();\n                \n                \/\/ Clear animated progress indicator\n                const resultsContainer = document.getElementById('visionResults');\n                if (resultsContainer) {\n                    resultsContainer.innerHTML = '';\n                }\n                \n                \/\/ Check for daily limit error in error response\n                if (!data.success && data.data && data.data.error === 'daily_limit_reached') {\n                    console.log('Daily limit reached:', data.data);\n                    \n                    \/\/ Update daily uploads count\n                    if (data.data.dailyUploadsCount !== undefined) {\n                        wpVision.dailyUploadsCount = data.data.dailyUploadsCount;\n                    }\n                    \n                    \/\/ Show gallery view again\n                    if (imageGalleryView) {\n                        imageGalleryView.style.display = 'block';\n                    }\n                    \n                    \/\/ Show daily limit warning\n                    const limitWarning = document.getElementById('visionDailyLimitWarning');\n                    if (limitWarning) {\n                        limitWarning.style.display = 'block';\n                        limitWarning.classList.add('show');\n                    }\n                    \n                    \/\/ Disable convert button\n                    if (convertButton) {\n                        convertButton.disabled = true;\n                        convertButton.classList.add('disabled-by-limit');\n                    }\n                    \n                    \/\/ Start countdown timer\n                    startLimitCountdown();\n                    \n                    \/\/ Show user-friendly message\n                    showError(data.data.message || 'Daily limit reached. Please try again tomorrow.');\n                    return;\n                }\n                \n                if (data.success) {\n                    console.log('AJAX request successful');\n                    \n                    \/\/ Update daily uploads count if provided in response\n                    if (data.data.dailyUploadsCount !== undefined) {\n                        wpVision.dailyUploadsCount = data.data.dailyUploadsCount;\n                        \n                        \/\/ If we've reached the limit during this upload, show warning after displaying results\n                        if (data.data.reachedLimit) {\n                            setTimeout(() => {\n                                const limitWarning = document.getElementById('visionDailyLimitWarning');\n                                if (limitWarning) {\n                                    limitWarning.style.display = 'block';\n                                    limitWarning.classList.add('show');\n                                }\n                                \n                                \/\/ Start countdown timer\n                                startLimitCountdown();\n                            }, 1000);\n                        }\n                    }\n                    \n                    \/\/ Display conversion results\n                    const results = data.data.results || data.data;\n                    displayResults(results);\n                } else {\n                    console.log('AJAX request failed:', data.data);\n                    showError(data.data || 'Error processing images');\n                    \n                    \/\/ Show gallery view again\n                    if (imageGalleryView) {\n                        imageGalleryView.style.display = 'block';\n                    }\n                    \n                    \/\/ Reset Turnstile if verification failed\n                    if (data.data && data.data.includes && data.data.includes('verification')) {\n                        turnstileToken = '';\n                        if (turnstileWidgetId) {\n                            turnstile.reset(turnstileWidgetId);\n                        }\n                        if (turnstileContainer) {\n                            turnstileContainer.style.display = 'block';\n                        }\n                    }\n                }\n            } catch (error) {\n                console.error('Error:', error);\n                showError('Network error occurred');\n                \n                \/\/ Show gallery view again\n                if (imageGalleryView) {\n                    imageGalleryView.style.display = 'block';\n                }\n                \n                \/\/ Clear animated progress indicator\n                const resultsContainer = document.getElementById('visionResults');\n                if (resultsContainer) {\n                    resultsContainer.innerHTML = '';\n                }\n            } finally {\n                \/\/ Reset button state\n                if (convertButton) {\n                    convertButton.disabled = false;\n                    convertButton.innerHTML = '<span class=\"dashicons dashicons-text-page\"><\/span> Convert';\n                }\n                \n                isSubmitting = false; \/\/ Reset submission status\n            }\n        }\n        \n        \/\/ Start limit countdown timer\n        function startLimitCountdown() {\n            const countdownElem = document.getElementById('limitCountdownTime');\n            if (!countdownElem) return;\n            \n            \/\/ Clear previous interval if any\n            if (window.limitCountdownInterval) {\n                clearInterval(window.limitCountdownInterval);\n            }\n            \n            \/\/ Update countdown time\n            function updateCountdown() {\n                const now = new Date();\n                const tomorrow = new Date();\n                tomorrow.setHours(24, 0, 0, 0);\n                \n                const diff = tomorrow - now;\n                const hours = Math.floor(diff \/ (1000 * 60 * 60));\n                const minutes = Math.floor((diff % (1000 * 60 * 60)) \/ (1000 * 60));\n                const seconds = Math.floor((diff % (1000 * 60)) \/ 1000);\n                \n                countdownElem.textContent = \n                    String(hours).padStart(2, '0') + ':' + \n                    String(minutes).padStart(2, '0') + ':' + \n                    String(seconds).padStart(2, '0');\n            }\n            \n            \/\/ Update immediately\n            updateCountdown();\n            \n            \/\/ Update every second\n            window.limitCountdownInterval = setInterval(updateCountdown, 1000);\n        }\n\n        \/\/ Display function for showing conversion results\n        function displayResults(resultData) {\n            const resultsContainer = document.getElementById('visionResults');\n            \n            \/\/ Make sure progress container is hidden\n            const progressContainer = document.getElementById('visionProgressContainer');\n            if (progressContainer) {\n                progressContainer.style.display = 'none';\n            }\n\n            \/\/ Make results container visible\n            if (resultsContainer) {\n                resultsContainer.style.display = 'block';\n            }\n\n            \/\/ Add class to body when results are shown\n            document.body.classList.add('vision-results-active');\n            \n            \/\/ Store original data in a global variable\n            window.visionResultData = resultData;\n            \n            \/\/ Create header HTML\n            const headerHtml = `\n                <div class=\"results-header mobile-friendly\">\n                    <div class=\"header-left\">\n                        <button type=\"button\" class=\"result-button return-button\" onclick=\"return returnToUpload(event)\" title=\"Return to upload\">\n                            <span class=\"dashicons dashicons-arrow-left-alt\"><\/span>\n                            <span class=\"button-text\">Back<\/span>\n                        <\/button>\n                    <\/div>\n                    <div class=\"header-center\">\n                        <div class=\"expand-controls\">\n                            <button type=\"button\" class=\"result-button toggle-all-button\" onclick=\"return toggleAllResults(event)\" title=\"Toggle expand\/collapse all\">\n                                <span class=\"dashicons dashicons-arrow-down-alt2\"><\/span>\n                                <span class=\"button-text\">Expand All<\/span>\n                            <\/button>\n                        <\/div>\n                    <\/div>\n                    <div class=\"header-right\">\n                        <button type=\"button\" class=\"result-button download-all-button\" onclick=\"return downloadAllResults(event)\" title=\"Download results as TXT or ZIP\">\n                            <span class=\"dashicons dashicons-download\"><\/span>\n                            <span class=\"button-text\">Download All<\/span>\n                        <\/button>\n                    <\/div>\n                <\/div>\n            `;\n\n            \/\/ Generate results HTML with accordion functionality\n            const resultsHtml = resultData.map((result, index) => {\n                if (result.error) {\n                    return `\n                        <div class=\"result-item\">\n                            <div class=\"result-header\">\n                                <h3>${result.fileName}<\/h3>\n                                <span class=\"toggle-icon dashicons dashicons-arrow-down-alt2\"><\/span>\n                            <\/div>\n                            <div class=\"result-body\">\n                                <div class=\"result-error\">${result.error}<\/div>\n                            <\/div>\n                        <\/div>\n                    `;\n                }\n                \n                \/\/ Get image URL from selected files\n                const originalImage = selectedFilesMap.get(Array.from(selectedFilesMap.keys()).find(key => \n                    selectedFilesMap.get(key).name === result.fileName\n                ));\n                const imageUrl = originalImage ? URL.createObjectURL(originalImage) : '';\n                \n                \/\/ First item expanded by default, others collapsed\n                const isExpanded = index === 0 ? 'expanded' : '';\n                \n                \/\/ Create truncated filename for display - more characters for desktop\n                const isMobile = window.innerWidth <= 768;\n                const isTablet = window.innerWidth > 768 && window.innerWidth <= 1024;\n                \/\/ Adjust character limits for different device types\n                const charLimit = isMobile ? 15 : (isTablet ? 30 : 60); \/\/ Shorter on mobile, medium on tablet, longer on desktop\n                const truncatedFileName = result.fileName.length > charLimit ? \n                    result.fileName.substring(0, charLimit - 3) + '...' : \n                    result.fileName;\n                \n                return `\n                    <div class=\"result-item ${isExpanded}\" data-id=\"${result.id}\">\n                        <div class=\"result-header\" onclick=\"toggleResultItem(this.parentElement)\">\n                            <table style=\"width:auto; border:none; margin:0; padding:0; border-spacing:0; border-collapse:collapse;\">\n                                <tr>\n                                    <td style=\"vertical-align:middle; padding:0; white-space:nowrap;\">\n                                        <span class=\"toggle-icon dashicons dashicons-arrow-down-alt2\"><\/span>\n                                        <h3 title=\"${result.fileName}\" style=\"display:inline-block; max-width:calc(100% - 10px); text-overflow:ellipsis; overflow:hidden;\">${truncatedFileName}<\/h3>\n                                    <\/td>\n                                <\/tr>\n                            <\/table>\n                            <div class=\"result-header-actions\">\n                                <button type=\"button\" class=\"item-action-btn preview-icon-btn vision-custom-btn\" onclick=\"event.stopPropagation(); openPreviewModal('${imageUrl}', '${result.fileName}', '${result.text.replace(\/'\/g, \"\\\\'\").replace(\/\\n\/g, \"\\\\n\")}')\" title=\"View Image and Text\">\n                                    <i class=\"fas fa-eye\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#0ea5e9 !important;\"><\/i>\n                                    <span class=\"btn-action-text\">Preview<\/span>\n                                <\/button>\n                                <button type=\"button\" class=\"item-action-btn copy-icon-btn vision-custom-btn\" onclick=\"event.stopPropagation(); return copyText(this, event)\" title=\"Copy Text\">\n                                    <i class=\"fas fa-copy\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#4f46e5 !important;\"><\/i>\n                                    <span class=\"btn-action-text\">Copy<\/span>\n                                <\/button>\n                                <button type=\"button\" class=\"item-action-btn download-icon-btn vision-custom-btn\" onclick=\"event.stopPropagation(); return visionDownloadText(this, event)\" title=\"Download Text\">\n                                    <i class=\"fas fa-file-download\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#2563eb !important;\"><\/i>\n                                    <span class=\"btn-action-text\">Download<\/span>\n                                <\/button>\n                            <\/div>\n                        <\/div>\n                        <div class=\"result-body\">\n                            <div class=\"result-content\">\n                                <div class=\"result-image-preview\">\n                                    <img decoding=\"async\" src=\"${imageUrl}\" alt=\"${result.fileName}\" onclick=\"openPreviewModal('${imageUrl}', '${result.fileName}', '${result.text.replace(\/'\/g, \"\\\\'\").replace(\/\\n\/g, \"\\\\n\")}')\">\n                                    <div class=\"image-click-indicator\" title=\"Click to view in detail\" onclick=\"openPreviewModal('${imageUrl}', '${result.fileName}', '${result.text.replace(\/'\/g, \"\\\\'\").replace(\/\\n\/g, \"\\\\n\")}')\">\n                                        <span class=\"dashicons dashicons-visibility\"><\/span>\n                                    <\/div>\n                                <\/div>\n                                <div class=\"result-text-container\">\n                                    <div class=\"result-text notranslate\" contenteditable=\"true\" translate=\"no\" data-notranslate>${result.text}<\/div>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                `;\n            }).join('');\n\n            \/\/ Add modal for enhanced preview\n            const modalHtml = `\n                <div class=\"vision-preview-modal\">\n                    <div class=\"modal-container\">\n                        <div class=\"modal-image-section\">\n                            <div class=\"modal-image-container\">\n                                <img decoding=\"async\" class=\"modal-image\" src=\"\" alt=\"\">\n                            <\/div>\n                            <div class=\"modal-image-controls\">\n                                <div class=\"image-control\" onclick=\"zoomImage(-0.1)\">\n                                    <span class=\"dashicons dashicons-minus\"><\/span>\n                                <\/div>\n                                <div class=\"image-control\" onclick=\"zoomImage(0.1)\">\n                                    <span class=\"dashicons dashicons-plus\"><\/span>\n                                <\/div>\n                                <div class=\"image-control\" onclick=\"rotateImage()\">\n                                    <span class=\"dashicons dashicons-redo\"><\/span>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                        <div class=\"modal-text-section\">\n                            <div class=\"modal-header\">\n                                <h3 class=\"modal-title\"><\/h3>\n                            <\/div>\n                            <div class=\"modal-text-content notranslate\" translate=\"no\" data-notranslate><\/div>\n                        <\/div>\n                        <div class=\"modal-close\" onclick=\"closePreviewModal()\">\n                            <span class=\"dashicons dashicons-no-alt\"><\/span>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            `;\n            \n            \/\/ Set container content and add event handlers\n            resultsContainer.innerHTML = headerHtml + resultsHtml + modalHtml;\n            \n            \/\/ Hide upload elements and show results\n            document.getElementById('imageGalleryView').style.display = 'none';\n            document.getElementById('initialUploadArea').style.display = 'none';\n            resultsContainer.style.display = 'block';\n        }\n\n        \/\/ Toggle accordion result item\n        window.toggleResultItem = function(item) {\n            \/\/ Close all items first\n            document.querySelectorAll('.result-item.expanded').forEach(expandedItem => {\n                if (expandedItem !== item) {\n                    expandedItem.classList.remove('expanded');\n                }\n            });\n            \n            \/\/ Toggle current item\n            item.classList.toggle('expanded');\n        }\n        \n        \/\/ Toggle all result items (expand\/collapse)\n        window.toggleAllResults = function(event) {\n            if (event) event.preventDefault();\n            \n            const button = event.currentTarget;\n            const isExpanded = button.getAttribute('data-expanded') === 'true';\n            \n            if (isExpanded) {\n                \/\/ Collapse all\n                document.querySelectorAll('.result-item').forEach(item => {\n                    item.classList.remove('expanded');\n                });\n                \n                \/\/ Update button\n                button.innerHTML = '<span class=\"dashicons dashicons-arrow-down-alt2\"><\/span><span class=\"button-text\">Expand All<\/span>';\n                button.setAttribute('data-expanded', 'false');\n            } else {\n                \/\/ Expand all\n                document.querySelectorAll('.result-item').forEach(item => {\n                    item.classList.add('expanded');\n                });\n                \n                \/\/ Update button\n                button.innerHTML = '<span class=\"dashicons dashicons-arrow-up-alt2\"><\/span><span class=\"button-text\">Collapse All<\/span>';\n                button.setAttribute('data-expanded', 'true');\n            }\n            \n            return false;\n        }\n        \n        \/\/ Copy text to clipboard\n        window.copyText = function(button, event) {\n            \/\/ Prevent any default action and stop event propagation\n            if (event) {\n                event.preventDefault();\n                event.stopPropagation();\n            }\n            \n            \/\/ Find the closest result item and get the text content\n            const resultItem = button.closest('.result-item');\n            const textContent = resultItem.querySelector('.result-text').textContent;\n            \n            \/\/ Save original icon for restoration\n            const originalIcon = button.innerHTML;\n            \n            \/\/ Use the clipboard API to copy the text\n            navigator.clipboard.writeText(textContent)\n                .then(() => {\n                    \/\/ Show success feedback - ONLY ICON, NO TEXT\n                    button.innerHTML = '<i class=\"fas fa-check\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#22c55e !important;\"><\/i>';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        button.innerHTML = originalIcon;\n                    }, 2000);\n                })\n                .catch(err => {\n                    console.error('Failed to copy text: ', err);\n                    \n                    \/\/ Show error feedback - ONLY ICON, NO TEXT\n                    button.innerHTML = '<i class=\"fas fa-exclamation-triangle\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#ef4444 !important;\"><\/i>';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        button.innerHTML = originalIcon;\n                    }, 2000);\n                });\n            \n            \/\/ Return false to prevent default action\n            return false;\n        }\n        \n        \/\/ Download text as file\n        window.visionDownloadText = function(button, event) {\n            \/\/ Prevent any default action and stop event propagation\n            if (event) {\n                event.preventDefault();\n                event.stopPropagation();\n            }\n            \n            \/\/ Find the closest result item and get necessary data\n            const resultItem = button.closest('.result-item');\n            const textContent = resultItem.querySelector('.result-text').textContent;\n            const fileName = resultItem.querySelector('.result-header h3').textContent;\n            \n            \/\/ Save original icon for restoration\n            const originalIcon = button.innerHTML;\n            \n            \/\/ Create a Blob with the text content\n            const blob = new Blob([textContent], {type: 'text\/plain;charset=utf-8'});\n            \n            \/\/ Use FileSaver.js to save the file\n            try {\n                \/\/ Show downloading feedback\n                button.innerHTML = '<i class=\"fas fa-spinner fa-spin\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#2563eb !important;\"><\/i>';\n                \n                \/\/ Download the file\n                saveAs(blob, fileName.replace(\/\\.[^\/.]+$\/, \"\") + '.txt');\n                \n                \/\/ Reset button after a delay\n                setTimeout(() => {\n                    button.innerHTML = originalIcon;\n                }, 2000);\n            } catch (err) {\n                console.error('Failed to download text: ', err);\n                \n                \/\/ Show error feedback\n                button.innerHTML = '<i class=\"fas fa-exclamation-triangle\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#ef4444 !important;\"><\/i>';\n                \n                \/\/ Reset button after a delay\n                setTimeout(() => {\n                    button.innerHTML = originalIcon;\n                }, 2000);\n            }\n            \n            \/\/ Return false to prevent default action\n            return false;\n        }\n        \n        \/\/ Open enhanced preview modal\n        window.openPreviewModal = function(imageUrl, fileName, textContent) {\n            const modal = document.querySelector('.vision-preview-modal');\n            const modalImage = modal.querySelector('.modal-image');\n            const modalTitle = modal.querySelector('.modal-title');\n            const modalTextContent = modal.querySelector('.modal-text-content');\n            \n            \/\/ Set content\n            modalImage.src = imageUrl;\n            modalImage.setAttribute('data-scale', '1');\n            modalImage.setAttribute('data-rotate', '0');\n            modalTitle.textContent = fileName;\n            \n            \/\/ Properly handle text formatting, preserving line breaks\n            const formattedText = textContent.replace(\/\\\\n\/g, \"\\n\");\n            \n            \/\/ Clear content\n            modalTextContent.innerHTML = '';\n            \n            \/\/ Split text into paragraphs and add to container\n            const paragraphs = formattedText.split(\"\\n\");\n            paragraphs.forEach(paragraph => {\n                if (paragraph.trim()) {\n                    const p = document.createElement('p');\n                    p.textContent = paragraph;\n                    p.style.margin = '0 0 12px 0';\n                    modalTextContent.appendChild(p);\n                } else {\n                    \/\/ Add extra spacing for empty lines\n                    const spacer = document.createElement('div');\n                    spacer.style.height = '12px';\n                    modalTextContent.appendChild(spacer);\n                }\n            });\n            \n            \/\/ Show modal\n            modal.classList.add('open');\n            document.body.style.overflow = 'hidden';\n        }\n        \n        \/\/ Close preview modal\n        window.closePreviewModal = function() {\n            const modal = document.querySelector('.vision-preview-modal');\n            modal.classList.remove('open');\n            document.body.style.overflow = '';\n        }\n        \n        \/\/ Image zoom functionality\n        window.zoomImage = function(delta) {\n            const modalImage = document.querySelector('.modal-image');\n            let scale = parseFloat(modalImage.getAttribute('data-scale') || '1');\n            scale = Math.max(0.5, Math.min(3, scale + delta));\n            modalImage.setAttribute('data-scale', scale);\n            modalImage.style.transform = `scale(${scale}) rotate(${modalImage.getAttribute('data-rotate')}deg)`;\n        }\n        \n        \/\/ Image rotate functionality\n        window.rotateImage = function() {\n            const modalImage = document.querySelector('.modal-image');\n            let rotate = parseInt(modalImage.getAttribute('data-rotate') || '0');\n            rotate = (rotate + 90) % 360;\n            modalImage.setAttribute('data-rotate', rotate);\n            modalImage.style.transform = `scale(${modalImage.getAttribute('data-scale')}) rotate(${rotate}deg)`;\n        }\n        \n        \/\/ Reset image transformation\n        window.resetImage = function() {\n            const modalImage = document.querySelector('.modal-image');\n            modalImage.setAttribute('data-scale', '1');\n            modalImage.setAttribute('data-rotate', '0');\n            modalImage.style.transform = 'scale(1) rotate(0deg)';\n        }\n        \n        \/\/ Download all texts (single TXT or ZIP for multiple)\n        window.downloadAllResults = function(event) {\n            \/\/ Prevent any default action\n            if (event) event.preventDefault();\n            \n            \/\/ Get all valid result items (excluding those with errors)\n            const resultItems = Array.from(document.querySelectorAll('.result-item'))\n                .filter(item => !item.querySelector('.result-error'));\n            \n            if (resultItems.length === 0) {\n                console.warn('No valid result items found');\n                return;\n            }\n            \n            \/\/ Show download status\n            const downloadBtn = document.querySelector('.download-all-button');\n            const originalText = downloadBtn.innerHTML;\n            \n            \/\/ If there's only one item, download it directly as TXT\n            if (resultItems.length === 1) {\n                const item = resultItems[0];\n                const fileName = item.querySelector('.result-header h3').textContent;\n                const textContent = item.querySelector('.result-text').textContent;\n                \n                \/\/ Update button text\n                downloadBtn.innerHTML = '<span class=\"dashicons dashicons-download\"><\/span> Downloading...';\n                \n                \/\/ Create and download a single text file\n                const blob = new Blob([textContent], {type: 'text\/plain;charset=utf-8'});\n                saveAs(blob, fileName.replace(\/\\.[^\/.]+$\/, \"\") + '.txt');\n                \n                \/\/ Update button to show success\n                downloadBtn.innerHTML = '<span class=\"dashicons dashicons-yes\"><\/span> Downloaded!';\n                \n                \/\/ Reset button after a delay\n                setTimeout(() => {\n                    downloadBtn.innerHTML = originalText;\n                }, 2000);\n                \n                return false;\n            }\n            \n            \/\/ For multiple items, create a ZIP file (existing logic)\n            \/\/ Check if JSZip is available\n            if (typeof JSZip === 'undefined') {\n                console.error('JSZip is not loaded');\n                return;\n            }\n            \n            \/\/ Update button for ZIP creation\n            downloadBtn.innerHTML = '<span class=\"dashicons dashicons-update rotating\"><\/span> Creating zip...';\n            \n            \/\/ Create a new zip file\n            const zip = new JSZip();\n            \n            \/\/ Add each text file to the zip\n            resultItems.forEach((item) => {\n                const fileName = item.querySelector('.result-header h3').textContent;\n                const textContent = item.querySelector('.result-text').textContent;\n                \n                \/\/ Add file to zip\n                zip.file(fileName.replace(\/\\.[^\/.]+$\/, \"\") + '.txt', textContent);\n            });\n            \n            \/\/ Generate the zip file\n            zip.generateAsync({type: 'blob'})\n                .then(blob => {\n                    \/\/ Use FileSaver.js to save the zip file\n                    saveAs(blob, 'converted_texts_' + new Date().toISOString().slice(0, 10) + '.zip');\n                    \n                    \/\/ Update button to show success\n                    downloadBtn.innerHTML = '<span class=\"dashicons dashicons-yes\"><\/span> Downloaded!';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        downloadBtn.innerHTML = originalText;\n                    }, 2000);\n                })\n                .catch(err => {\n                    console.error('Failed to create zip file: ', err);\n                    \n                    \/\/ Show error on button\n                    downloadBtn.innerHTML = '<span class=\"dashicons dashicons-warning\"><\/span> Error!';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        downloadBtn.innerHTML = originalText;\n                    }, 2000);\n                });\n        }\n\n        \/\/ Check daily limit on page load\n        if (wpVision && wpVision.dailyUploadsCount !== undefined && wpVision.dailyLimit !== undefined) {\n            if (!wpVision.isSubscriber && wpVision.dailyUploadsCount >= wpVision.dailyLimit) {\n                const limitWarning = document.getElementById('visionDailyLimitWarning');\n                if (limitWarning) {\n                    limitWarning.style.display = 'block';\n                    limitWarning.classList.add('show');\n                    \n                    \/\/ Disable convert button\n                    if (convertButton) {\n                        convertButton.disabled = true;\n                        convertButton.classList.add('disabled-by-limit');\n                    }\n                    \n                    \/\/ Start the countdown\n                    startLimitCountdown();\n                }\n            }\n        }\n    }\n});\n<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d16387d elementor-widget elementor-widget-html\" data-id=\"d16387d\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\r\n    * {\r\n      margin: 0;\r\n      padding: 0;\r\n      box-sizing: border-box;\r\n      font-family: 'Segoe UI', 'SF Pro Display', Arial, sans-serif;\r\n    }\r\n    \r\n    body {\r\n      background-color: #fafafa;\r\n    }\r\n    \r\n    .premium-features {\r\n      display: flex;\r\n      justify-content: center;\r\n      flex-wrap: wrap;\r\n      gap: 16px;\r\n      padding: 20px 10px;\r\n      max-width: 900px;\r\n      margin: 0 auto;\r\n    }\r\n    \r\n    .premium-badge {\r\n      display: flex;\r\n      align-items: center;\r\n      gap: 12px;\r\n      background-color: white;\r\n      padding: 10px 16px;\r\n      border-radius: 50px;\r\n      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\r\n      transition: all 0.3s ease;\r\n      border: 1px solid rgba(0, 0, 0, 0.05);\r\n    }\r\n    \r\n    .premium-badge:hover {\r\n      transform: translateY(-3px);\r\n      box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);\r\n    }\r\n    \r\n    .badge-icon {\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      width: 28px;\r\n      height: 28px;\r\n      border-radius: 50%;\r\n      color: white;\r\n      font-size: 14px;\r\n    }\r\n    .premium-badge:nth-child(1) .badge-icon {\r\n      background: linear-gradient(135deg, #ff6f00 0%, #ff8f00 100%);\r\n    }\r\n\r\n    .premium-badge:nth-child(2) .badge-icon {\r\n      background: linear-gradient(135deg, #ab47bc 0%, #8e24aa 100%);\r\n    }\r\n\r\n    .premium-badge:nth-child(3) .badge-icon {\r\n      background: linear-gradient(135deg, #00c853 0%, #009624 100%);\r\n    }\r\n    \r\n    .badge-icon svg {\r\n      width: 16px;\r\n      height: 16px;\r\n      fill: none;\r\n      stroke: currentColor;\r\n      stroke-width: 2;\r\n      stroke-linecap: round;\r\n      stroke-linejoin: round;\r\n    }\r\n    \r\n    .badge-text {\r\n      font-size: 14px;\r\n      font-weight: 600;\r\n      color: #333;\r\n    }\r\n    \r\n    \/* Media queries for responsiveness *\/\r\n    @media (max-width: 768px) {\r\n      .premium-features {\r\n        padding: 15px 10px;\r\n      }\r\n    }\r\n    \r\n    @media (max-width: 480px) {\r\n      .premium-features {\r\n        flex-direction: column;\r\n        align-items: center;\r\n      }\r\n      \r\n      .premium-badge {\r\n        width: 100%;\r\n        max-width: 260px;\r\n        justify-content: flex-start;\r\n      }\r\n    }\r\n  <\/style>\r\n<\/head>\r\n<body>\r\n  <div class=\"premium-features\">\r\n    <div class=\"premium-badge\">\r\n      <div class=\"badge-icon\">\r\n        <svg viewBox=\"0 0 24 24\">\r\n          <circle cx=\"12\" cy=\"12\" r=\"10\"><\/circle>\r\n          <line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\"><\/line>\r\n          <path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"><\/path>\r\n        <\/svg>\r\n      <\/div>\r\n      <div class=\"badge-text\">Supports 100+ Languages<\/div>\r\n    <\/div>\r\n    \r\n    <div class=\"premium-badge\">\r\n      <div class=\"badge-icon\">\r\n        <svg viewBox=\"0 0 24 24\">\r\n          <path d=\"M20 6L9 17l-5-5\"><\/path>\r\n        <\/svg>\r\n      <\/div>\r\n      <div class=\"badge-text\">99.8% Accuracy<\/div>\r\n    <\/div>\r\n    \r\n    <div class=\"premium-badge\">\r\n      <div class=\"badge-icon\">\r\n        <svg viewBox=\"0 0 24 24\">\r\n          <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"><\/rect>\r\n          <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"><\/path>\r\n        <\/svg>\r\n      <\/div>\r\n      <div class=\"badge-text\">Secure & Private<\/div>\r\n    <\/div>\r\n  <\/div>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-a8e0e56 e-flex e-con-boxed e-con e-parent\" data-id=\"a8e0e56\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-777805e elementor-widget elementor-widget-shortcode\" data-id=\"777805e\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><script async src=\"https:\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js?client=ca-pub-8069529413860845\"\n     crossorigin=\"anonymous\"><\/script>\n<!-- 1000-100 -->\n<ins class=\"adsbygoogle\"\n     style=\"display:inline-block;width:1000px;height:100px\"\n     data-ad-client=\"ca-pub-8069529413860845\"\n     data-ad-slot=\"9855343712\"><\/ins>\n<script>\n     (adsbygoogle = window.adsbygoogle || []).push({});\n<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7b03df09 e-flex e-con-boxed e-con e-parent\" data-id=\"7b03df09\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-825ef95 elementor-widget elementor-widget-heading\" data-id=\"825ef95\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Features<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-45d363cb elementor-widget elementor-widget-ucaddon_uc_material_bullets\" data-id=\"45d363cb\" data-element_type=\"widget\" data-widget_type=\"ucaddon_uc_material_bullets.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!-- start Icon Bullets -->\n\t\t<link id='font-awesome-css' href='https:\/\/ocr365.com\/wp-content\/plugins\/unlimited-elements-for-elementor-premium\/assets_libraries\/font-awesome6\/fontawesome-all.min.css' type='text\/css' rel='stylesheet' >\n\t\t<link id='font-awesome-4-shim-css' href='https:\/\/ocr365.com\/wp-content\/plugins\/unlimited-elements-for-elementor-premium\/assets_libraries\/font-awesome6\/fontawesome-v4-shims.min.css' type='text\/css' rel='stylesheet' >\n\n<style>\/* widget: Icon Bullets *\/\n\n\n\n#uc_uc_material_bullets_elementor_45d363cb *{\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .ue-icon-wrapper{\n\tdisplay: flex;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .ue-icon{\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  flex-grow:0;\n  flex-shrink:0;\n  line-height:1em;\n  transition:0.3s;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .ue-icon svg{\n  height:1em;\n  width:1em;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .uc_material_bullets_row{\n\tfont-weight:400;\n\toverflow:hidden;\n\tdisplay:flex;\n\tposition:relative;\n\ttext-align:left;\n\twidth:100%;   \n    transition:0.3s;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .uc_material_bullets_row a.ue-item-link{\n  position:absolute;\n  display:block;\n  top:0;\n  right:0;\n  left:0;\n  bottom:0;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .uc_material_bullets_row:last-child{\n\tmargin-bottom:0px !important;\n}\n\n\n#uc_uc_material_bullets_elementor_45d363cb .uc_material_bullets_row {\n\tposition:relative;\n\tvertical-align:middle;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .uc_material_bullets_row .uc_content_box{\n\tdisplay:flex;\n    flex-direction:column;\n    justify-content:center;\n    align-items: flex-start;\n    flex-grow:1;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .ue-bullets{\n  display:grid;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .ue-text, \n#uc_uc_material_bullets_elementor_45d363cb .ue-title, \n#uc_uc_material_bullets_elementor_45d363cb .ue-seperator{\n  width:100%;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .ue-seperator-line{\n  display:inline-block;\n  font-size:0px;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .ue-seperator{\n  font-size:0px;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb.uc-remote-parent .uc_material_bullets_row{\n  cursor:pointer;\n}\n\n.ue-title{\n  font-size:21px;\n  margin:0;\n}\n\n#uc_uc_material_bullets_elementor_45d363cb .uc_content_box > *{\n  transition: all .3s;\n}\n\n<\/style>\n\n<div class=\"uc_material_bullets  \"  id=\"uc_uc_material_bullets_elementor_45d363cb\"  >   \t\n    \t<div class=\"ue-bullets uc-items-wrapper\">\n          \t<div class=\"uc_material_bullets_row elementor-repeater-item-4061aae\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">1<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">No Registration<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Convert GIF to text instantly without the need to sign up or log in. Simple and hassle-free!<\/div>\t\n  <\/div>\n    \t\n<\/div>\n<div class=\"uc_material_bullets_row elementor-repeater-item-c647ca0\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">2<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">Easy Conversion<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Upload your GIF and get the extracted text in seconds. No complicated steps required!<\/div>\t\n  <\/div>\n    \t\n<\/div>\n<div class=\"uc_material_bullets_row elementor-repeater-item-6336972\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">3<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">99.8% Accuracy<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Our advanced OCR technology ensures highly precise text extraction with 99.8% accuracy.<\/div>\t\n  <\/div>\n    \t\n<\/div>\n<div class=\"uc_material_bullets_row elementor-repeater-item-ed5c934\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">4<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">100+ Languages<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Our tool extracts text from GIFs in 100+ languages, handling global content.<\/div>\t\n  <\/div>\n    \t\n<\/div>\n\n      <\/div>\n<\/div>\n<!-- end Icon Bullets -->\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5c91695 elementor-widget elementor-widget-text-editor\" data-id=\"5c91695\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 style=\"text-align: center;\"><strong>What is a GIF to Text Converter?<\/strong><\/h3><p>The GIF to Text Converter is a user-friendly, online tool that allows you to extract text from GIFs in a simple and fast way. By leveraging OCR technology, it analyzes each frame of a GIF to recognize and extract any embedded text. Whether you\u2019re working with animated GIFs or static images, this tool can help you convert GIFs to text effortlessly.<\/p><h3 style=\"text-align: center;\"><strong>The Benefits of Converting GIFs to Text<\/strong><\/h3><div><p class=\"break-words\">Why bother with this tool? Let\u2019s talk about the perks\u2014it\u2019s more useful than you might think.<\/p><h4><strong>Save Time and Skip the Typing<\/strong><\/h4><p class=\"break-words\">Transcribing text from a GIF by hand is a drag. If the animation has multiple frames or tiny text, you\u2019re squinting at your screen, pausing and typing, hoping you don\u2019t miss a word. This tool does it instantly. What might take you 10 minutes becomes a 10-second job. For busy people\u2014like me, juggling deadlines\u2014it\u2019s a lifesaver.<\/p><h4><strong>Make Content More Accessible<\/strong><\/h4><p class=\"break-words\">Accessibility matters. Not everyone can easily read text in a fast-moving GIF, especially those with visual impairments. Once you extract the text, you can plug it into a screen reader or enlarge it for better visibility. It\u2019s a small step that makes a big difference, whether you\u2019re sharing with friends or reaching a wider audience.<\/p><h4><strong>Edit and Repurpose with Ease<\/strong><\/h4><p class=\"break-words\">Once the text is out, it\u2019s yours to play with. Want to tweak a quote from a GIF? Translate it into another language? Pop it into a presentation? You can. I\u2019ve used this to grab funny lines from memes and turn them into social media posts\u2014way faster than starting from scratch.<\/p><p class=\"break-words\">These benefits add up, making the tool a practical addition to your digital toolkit.<\/p><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-798fd0fd elementor-widget elementor-widget-heading\" data-id=\"798fd0fd\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">How to Convert GIF to Text ?\n<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-19f54626 elementor-widget elementor-widget-ucaddon_step_process\" data-id=\"19f54626\" data-element_type=\"widget\" data-widget_type=\"ucaddon_step_process.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!-- start Step Process -->\n\n<style>\/* widget: Step Process *\/\n\n#uc_step_process_elementor_19f54626\n{\n  display:flex;\n}\n\n#uc_step_process_elementor_19f54626 .ue-link\n{\n  display:block;\n  position:absolute;\n  top:0px;\n  bottom:0px;\n  left:0px;\n  right:0px;\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-item\n{\n  flex:1;\n  display:flex;\n  flex-direction:column;\n  position:relative;\n}\n#uc_step_process_elementor_19f54626 .ue-item-highlight\n{\n  display: flex;\n  align-items:center;\n  \n}\n\n#uc_step_process_elementor_19f54626 .ue-step-item-gap\n{\n  flex-grow:0;\n  flex-shrink:0;\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-item-line\n{\n  height:1px;\n  flex-grow:1;\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-icon\n{\n  display:flex;\n  justify-content:center;\n  align-items:center;\n  flex-grow:0;\n  flex-shrink:0;\n  position:relative;\n  line-height:1em;\n  transition:0.3s;\n}\n\n#uc_step_process_elementor_19f54626 .ue-icon svg\n{\n  height:1em;\n  width:1em;\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-label\n{\n  position:absolute;\n  left:0px;\n  top:0px;\n  display:flex;\n  justify-content:center;\n  align-items:center;\n}\n.ue-step-label\n{\n  font-size:9px;\n  line-height:1em;\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-item-content\n{\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-item:last-child .ue-step-item-line:last-child\n{\n  opacity:0;\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-item:first-child .ue-step-item-line:first-child\n{\n  opacity:0;\n}\n\n#uc_step_process_elementor_19f54626 .ue-step-item-spacer\n{\n  flex-grow:0;\n  flex-shrink:0;\n  \n}\n\n#uc_step_process_elementor_19f54626 .ue-graphic-image img\n{\n  \n}\n\n\n#uc_step_process_elementor_19f54626.uc-remote-parent .ue-step-item\n{\n  cursor:pointer;\n}\n\n\n\n\n\n\n@media only screen and (max-width: 768px) {\n  #uc_step_process_elementor_19f54626\n    {\n      flex-direction:column;\n    }\n  \n  #uc_step_process_elementor_19f54626 .ue-step-item\n  {\n    flex-direction:row;\n  }\n  \n  #uc_step_process_elementor_19f54626 .ue-item-highlight\n  {\n    flex-direction:column;\n  }\n  \n   #uc_step_process_elementor_19f54626 .ue-step-item .ue-step-item-line:first-child\n    {\n      display:none;\n    }\n  \n\n    #uc_step_process_elementor_19f54626  .ue-step-item-gap:nth-child(2)\n     {\n      display:none;    \n      }\n   #uc_step_process_elementor_19f54626  .ue-step-item-line:first-child\n      {\n      display:none;    \n      }\n  \n    #uc_step_process_elementor_19f54626  .ue-step-item-line\n      {\n        height:100%;\n        width:1px;\n      }\n}\n\n\n\n<\/style>\n\n<div id=\"uc_step_process_elementor_19f54626\" class=\"uc-items-wrapper  \"  >\n <div class=\"ue-step-item ue-item elementor-repeater-item-b77fdec\">\n    <div class=\"ue-item-highlight\">\n      \n      <div class=\"ue-step-item-line\"><\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-icon \">\n        <span class=\"ue-icon\"><i class='fas fa-photo-video'><\/i><\/span>                        \n              <\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-item-line\"><\/div>\n      \n    <\/div>\n    \n    <div class=\"ue-step-item-spacer\"><\/div>\n    \n    <div class=\"ue-step-item-content\">  \n       <div class=\"ue-step-item-content-title\">Upload Your GIF<\/div>       <div class=\"ue-step-item-content-text\">Select and upload your GIF file to the tool.<\/div>    <\/div>\n  \n    <\/div>\n<div class=\"ue-step-item ue-item elementor-repeater-item-fea387d\">\n    <div class=\"ue-item-highlight\">\n      \n      <div class=\"ue-step-item-line\"><\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-icon \">\n        <span class=\"ue-icon\"><i class='fas fa-cloud-upload-alt'><\/i><\/span>                        \n              <\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-item-line\"><\/div>\n      \n    <\/div>\n    \n    <div class=\"ue-step-item-spacer\"><\/div>\n    \n    <div class=\"ue-step-item-content\">  \n       <div class=\"ue-step-item-content-title\">Extract Text Automatically<\/div>       <div class=\"ue-step-item-content-text\">The system will process and recognize the text in seconds.<\/div>    <\/div>\n  \n    <\/div>\n<div class=\"ue-step-item ue-item elementor-repeater-item-4860be0\">\n    <div class=\"ue-item-highlight\">\n      \n      <div class=\"ue-step-item-line\"><\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-icon \">\n        <span class=\"ue-icon\"><i class='fas fa-sync'><\/i><\/span>                        \n              <\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-item-line\"><\/div>\n      \n    <\/div>\n    \n    <div class=\"ue-step-item-spacer\"><\/div>\n    \n    <div class=\"ue-step-item-content\">  \n       <div class=\"ue-step-item-content-title\">Copy or Download<\/div>       <div class=\"ue-step-item-content-text\">Retrieve the extracted text and save it as needed.<\/div>    <\/div>\n  \n    <\/div>\n\n<\/div>\n<!-- end Step Process -->\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0d92f4f elementor-widget elementor-widget-text-editor\" data-id=\"0d92f4f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div><h3 style=\"text-align: center;\"><strong>Solving Common Problems with GIF-to-Text Conversion<\/strong><\/h3><p class=\"break-words\">No tool is perfect, and converting GIFs to text can hit some bumps. Here\u2019s how to handle them.<\/p><h4><strong>Problem 1: Blurry or Low-Quality GIFs<\/strong><\/h4><p class=\"break-words\">If your GIF is pixelated or the text is fuzzy, the tool might struggle to read it accurately. I\u2019ve run into this with old GIFs from sketchy websites.<\/p><ul class=\"marker:text-secondary\"><li class=\"break-words\"><strong>Solution:<\/strong> Start with a high-quality GIF if you can. If not, try sharpening it with free image editors like GIMP or online tools before uploading. A clearer image means better results.<\/li><\/ul><h4><strong>Problem 2: Tricky Text Layouts<\/strong><\/h4><p class=\"break-words\">GIFs with text over busy backgrounds or funky fonts\u2014like cursive or neon styles\u2014can confuse the OCR. I once tested a GIF with text swirling around, and it tripped up a bit.<\/p><ul class=\"marker:text-secondary\"><li class=\"break-words\"><strong>Solution:<\/strong> Stick to GIFs with clear, standard fonts when possible. The tool\u2019s smart, but simpler layouts help it shine. If the text is artsy, double-check the output and edit any oddities.<\/li><\/ul><h4><strong>Problem 3: Text in Other Languages<\/strong><\/h4><p class=\"break-words\">What if your GIF isn\u2019t in English? Not every tool handles multiple languages well, and accuracy can drop.<\/p><ul class=\"marker:text-secondary\"><li class=\"break-words\"><strong>Solution:<\/strong> Our tool supports several languages\u2014English, Spanish, French, and more. Check the settings to match your GIF\u2019s language. If it\u2019s still off, reach out to support; they\u2019re usually quick to help.<\/li><\/ul><p class=\"break-words\">These fixes keep the process smooth, even when things get tricky.<\/p><h3 style=\"text-align: center;\"><strong>How Our Tool Stands Out from the Crowd<\/strong><\/h3><p class=\"break-words\">There are other ways to extract text from images, but our GIF-to-text tool has an edge. Let\u2019s compare.<\/p><h4><strong>Vs. Basic Image OCR Tools<\/strong><\/h4><p class=\"break-words\">Standard OCR tools\u2014like those for scanning PDFs\u2014work fine for still images but falter with GIFs. They might grab text from one frame and miss the rest. Our tool tackles every frame, ensuring nothing slips through.<\/p><h4><strong>Vs. Manual Selection Tools<\/strong><\/h4><p class=\"break-words\">Some alternatives make you highlight text areas frame by frame\u2014a tedious chore. I tried one once and gave up after two minutes. Ours is fully automated; you just upload and go.<\/p><h4><strong>What Makes Ours Better<\/strong><\/h4><p class=\"break-words\">It\u2019s the combo of GIF-specific OCR and user-friendly design. Plus, it\u2019s fast and accurate with clear GIFs\u2014often above 95% right in my tests. That beats retyping any day.<\/p><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4317d10 elementor-widget elementor-widget-shortcode\" data-id=\"4317d10\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">\n\n<div class=\"kk-star-ratings kksr-shortcode\"\n    data-payload='{&quot;id&quot;:&quot;712&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;shortcode&quot;,&quot;align&quot;:&quot;&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;5&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;valign&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;5&quot;,&quot;greet&quot;:&quot;Rate this page&quot;,&quot;legend&quot;:&quot;5\\\/5 - (5 votes)&quot;,&quot;size&quot;:&quot;15&quot;,&quot;title&quot;:&quot;GIF to Text&quot;,&quot;width&quot;:&quot;97.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 97.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 12px;\">\n            5\/5 - (5 votes)    <\/div>\n    <\/div>\n<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>GIF to Text Supports 100+ Languages 99.8% Accuracy Secure &#038; Private Features 1 No Registration Convert GIF to text instantly without the need to sign up or log in. Simple and hassle-free! 2 Easy Conversion Upload your GIF and get the extracted text in seconds. No complicated steps required! 3 99.8% Accuracy Our advanced OCR [&#8230;]\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-712","page","type-page","status-publish","hentry"],"rankMath":{"parentDomain":"ocr365.com","noFollowDomains":[],"noFollowExcludeDomains":[],"noFollowExternalLinks":false,"featuredImageNotice":"Gambar yang ditampilkan harus setidaknya 200 x 200 piksel untuk diambil oleh Facebook dan situs media sosial lainnya.","pluginReviewed":false,"postSettings":{"linkSuggestions":true,"useFocusKeyword":false},"frontEndScore":false,"postName":"gif-to-text","permalinkFormat":"https:\/\/ocr365.com\/id\/%pagename%\/","showLockModifiedDate":true,"assessor":{"focusKeywordLink":"https:\/\/ocr365.com\/wp-admin\/edit.php?focus_keyword=%focus_keyword%&post_type=%post_type%","hasTOCPlugin":true,"primaryTaxonomy":false,"serpData":{"title":"Konversi GIF ke Teks Online Gratis","description":"Ubah GIF menjadi teks secara online dengan mudah dan gratis. Konversi cepat, akurat, dan mudah hanya dengan beberapa klik!","focusKeywords":"GIF to Text","pillarContent":false,"canonicalUrl":"","breadcrumbTitle":"","advancedRobots":{"max-snippet":"-1","max-video-preview":"-1","max-image-preview":"large"},"facebookTitle":"","facebookDescription":"","facebookImage":"","facebookImageID":"","facebookHasOverlay":false,"facebookImageOverlay":"","facebookAuthor":"","twitterCardType":"","twitterUseFacebook":true,"twitterTitle":"","twitterDescription":"","twitterImage":"","twitterImageID":"","twitterHasOverlay":false,"twitterImageOverlay":"","twitterPlayerUrl":"","twitterPlayerSize":"","twitterPlayerStream":"","twitterPlayerStreamCtype":"","twitterAppDescription":"","twitterAppIphoneName":"","twitterAppIphoneID":"","twitterAppIphoneUrl":"","twitterAppIpadName":"","twitterAppIpadID":"","twitterAppIpadUrl":"","twitterAppGoogleplayName":"","twitterAppGoogleplayID":"","twitterAppGoogleplayUrl":"","twitterAppCountry":"","robots":{"index":true},"twitterAuthor":"nama pengguna","primaryTerm":0,"authorName":"admin","titleTemplate":"%title% %sep% %sitename%","descriptionTemplate":"%excerpt%","showScoreFrontend":true,"lockModifiedDate":false},"powerWords":["abadi","absolut","agenda rahasia","agresif","ahli","ahmak","ajaib","aktif","akui","alamiah","alur rahasia","aman","aneh","anggaran","anggun","angkuh","animasi","animo","anonim","anti gagal","antusias","apakah anda tahu","argumentatif","asing","asli","asusila","asyik","autentik","awas","ayem","aziz","azmat","badai","badut","bagaimana cara","bagi hadiah","bahagia","bahaya","balas dendam","banget","bangsat","bantahan","banter","banyak akal","baru","baru saja tiba","batalkan kapan saja","batas waktu","batu sandungan","bawah tanah","bebas rasa bersalah","bejat","beli","belum dimanfaatkan","belum pernah terjadi","benar-benar","bencana alam","benci","beneran","bengis","bengkok","beracun","berahi","berani","berapi","berbahagia","berbahaya","berbakti","berbisa","berdarah","berdarah dingin","berdosa","berfokus","bergeliat","bergelombang","berguna","berharap","berharga","berhasil","berhasrat","berhawa-nafsu","berisiko","berjiwa","berkedut","berkelakar","berkembang","berkeringat","berkesan","berkuasa","berkurang","berlimpah","bermanfaat","bermusuhan","berpusat","bersandaran","bersemangat","berseri","berseri-seri","bersertifikat","berseteru","bersih","bersinar","bersorak","bersyukur","bertahan","bertahan hidup","bertambah","bertanggung jawab","bertarung","bertenaga","berterimakasih","bertumbuh","beruap","berubah","berwenang","besar","besar-besaran","bikin emosi","bikin malu","bikin mual","bikin ngiler","bimbang","binal","bingung","bisa beradaptasi","bocoran","bodoh","bohong","bokek","bom","bombardir","bonus","boros","brutal","buas","budak","bui","bukan main","buntut","bunuh","buruan","busuk","busung","buta","cabul","cahaya","cairan","cambuk","canggung","cantik","caruk","cekatan","cemerlang","cengis","cepat","cerah","cerdas","cerewet","ceroboh","cinta","congkak","contekan","contoh","cukup","cukup besar","cukupan","curang","curiga","daftar hitam","dahsyat","daif","dalam","dalam waktu dekat","dapat diandalkan","dapat dikembalikan","dapat ditindaklanjuti","darurat","dasar","daya ingat","definitif","deg-degan","demoralisasi","denda","dendam","dengan cepat","dengan mudah","dengan sedih","dengan serius","derita","detik akhir","di bawah harga","di dalam zona","di sini","diakui","diam","diancam","diasingkan","dibalik layar","diberdayakan","diberkati","dibodohi","dibunuh","dicari","dicatat","dicekok","didiagnosis","didukung","dihukum","dilanggar","dilarang","dilepaskan","dimainkan","dimarahi","dinamis","dipecat","dipercaya","disampaikan","disayangkan","disederhanakan","diselundupkan","disensor","disetujui","diskon","disokong","ditahan","ditandai","ditargetkan","dites","ditipu","diwajibkan","dobel","dokumen","dolar","dominasi","dorongan","dosa","dosa-dosa","durjana","edan","edukatif","efektif","efisien","ekonomis","eksklusif","eksplosif","ekstra","elite","elok","enam angka","eneq","energi","energik","enteng","epidemis","epik","etis","euforia","fantasi","final","fokus","frustrasi","fundamental","gaduh","gagah","gagal","gagal total","gaib","gairah","galak","gampang","ganjil","garang","gasang","gawat","gede","gelap","geli","gelisah","gelora","gembira","gemetar","gengsi","geram","gila","gila hormat","glamor","goblok","godaan","gratis","gravitasi","grogi","gugatan","gugup","gundah","gusar","hadiah","hak istimewa","hakekat","hancur","haram","harapan","harfiah","harga","harga diri","hari ini","hari penghakiman","harta","harus","hasil","hati","hebat","heboh","hemat","hidup","hina","hingar-bingar","hipnosis","hipnotik","hiruk-pikuk","hoaks","hoax","horor","humor","idiot","ilusif","imajinasi","iman","indah","informatif","inkonvensional","inovatif","inspirasi","intel","intens","interesan","intinya","invasi","investasi","iri","irs","istirahat","jackpot","jagoan","jagur","jahat","jahil","jarang","jatuh","jebakan","jelek","jeles","jelimet","jenazah","jengkel","jenius","jijik","jinak","jorok","jubilant","judi","jujur","kacau","kado","kaget","kalah","kasar","kaya","keahlian","keajaiban","keamanan","kebahagiaan","kebaruan","kebebasan","kebenaran","keberanian","kebesaran","kebiadaban","kebohongan","kecanggungan","kecantikan","kecerobohan","kecewa","kedahsyatan","keeksklusifan","kegagahan","kegagalan","kegembiraan","kegigihan","kegirangan","kehilangan","kejam","kejelasan","kejut","kejutan","kejutkan","kekalahan","kekeliruan","kekosenan","kekurangan","kelancangan","kelas master","kelengkapan","kelimpungan","keluhuran","kemaruk","kematian","kemelaratan","kemenangan","kenalan","kengerian","kentara","kepeloporan","kepercayaan","keperkasaan","keracak","kerakusan","keramahan","keras","keras kepala","keringat","kesakitan","kesalahan","kesederhanaan","kesedihan","keselamatan","kesempatan terakhir","kesepian","ketakutan","keteguhan hati","ketekunan","keterlaluan","ketidakberdayaan","ketidaksabaran","keunggulan","keuntungan","kewalahan","keyakinan","khidmat","kiamat","kiat","kickstart","kikuk","kokoh","kolosal","kompetitif","komprehensif","kompromi","konfidensi","konstruktif","kontan","kontroversi","konyol","kooperatif","kopi","korban","korupsi","kotor","kreatif","krisis","kritis","kualitas","kuat","kuno","kurang ajar","kurang dimanfaatkan","kusut","kw","laba","langka","langkah","langsung","laporan","larangan","lawan","lebih bagus","lebih baik","ledakan","lega","legendaris","lelah","lemah","lengkap","lezat","liar","liberal","licik","licin","lihai","limbah","lincah","lipat empat","lonjakan","luar biasa","lucu","luka berat","lumpuh","luwes","mabuk","mahal","mainstream","makarya","makmur","mala","malapetaka","malas","malu","mampu","manipulatif","manis sekali","manjur","mantul","manusia super","mara","marah","masalah","masif","masih","master","mata duitan","mati","mati kutu","mayat","megah","melayang","meledak","meleleh","melena","melepaskan","meletus","melindungi","melongo","melonjak","melontarkan","melumpuhkan","meluncurkan","memaafkan","memalukan","mematikan","membakar","membalas","membandingkan","membenci diri sendiri","memberontak","membinasakan","membocorkan","membuat","membuat ulang","membubung","membuka mata","membunuh","memenuhi","memerah","memetik","memikat","memikat hati","memilukan","memperberat","memperdaya","memperkenalkan","mempermalukan","mempesona","mempesonakan","memprovokasi","memromosikan","memuakkan","memukau","memukul","memusnahkan","memvalidasi","menakjubkan","menakuntukan","menakuti","menakutkan","menang","menangis","menantang","menarik","menawan","mencapai","mencegah","mencekik","mencengkeram","mencolok","mencuri","mencurigakan","mendalam","mendebarkan","menderita","mendesak","mendobrak","mendukung","menegur","menekankan","menemukan","menendang","menentang","menewaskan","mengagumkan","mengaku","mengakui","mengalahkan","mengancam","mengangkat","menganiaya","mengatasi","mengejuntukan","mengeksploitasi","mengerikan","mengerti","mengesankan","mengetahui semua","menggelisahkan","menggemparkan","menggenjot","menggerakkan","menggertakkan","menggilas","menggoda","menghancurkan","menghapuskan","mengharukan","menghebohkan","mengherankan","menghina","menghukum","mengibuli","mengidam","mengigau","menginspirasi","mengintai","mengintimidasi","menguangkan","menguap","menguasai","mengubah","mengubah hidup","mengulangi","mengumumkan","mengungkap","mengungkapkan","menguntungkan","mengutuk","meningkatkan","menipu","menjanjikan","menjerumuskan","menjijikkan","menjilat","menjulang","menolak","menuduh","menundukkan","menunggu","menusuk dari belakang","menutupi","menyabotase","menyakitkan","menyalakan","menyarankan","menyayat","menyelundupkan","menyemangati","menyeramkan","menyerang","menyetujui","menyihir","menyiksa","menyilaukan","menyogok","menyolok","menyoroti","menyuap","meracuni","merangsang","merayu","merebut","merendahkan","merenungkan","meriah","meroket","merosot","merugikan","mewah","meyakinkan","milik","milyar","mimpi buruk","minat","minimalis","miskin","misteri","molek","muak","mudah","mudah dipahami","mulai cepat","mulia","muncul","mungkin","murah","nafsu","naik pitam","naim","nakal","nanah","nasib","nazi","neraka","ngaco","ngakak","ngeri","ngiler","nilai","niscaya","nol rupiah","nyaman","obral","obsesi","oke","omong kosong","optimis","optimistis","orang bodoh","orang dalam","orang gila","orisinil","padat","pahala","pahlawan","paling besar","paling dahsyat","paling efektif","paling lucu","palsu","pandir","panik","parah","pasar gelap","pasti","pastinya","pastinya paling rendah","patut diperhatikan","pecah","pecinta kesenangan","pecundang","pedih","peka","pelanggaran","peluang","peluncuran","pembantaian","pembunuhan","pemecahan","pemicu","pemula","penaklukan","pendendam","pendengki","penemuan","penerobosan","pengakuan","pengecut","pengembalian","pengembalian dana","penghakiman","penghancuran","penghinaan","pengungsi","penipu","penipuan","penjahat","penjara","penjualan terbaik","penting","penuh","penuh dosa","penuh kepercayaan","penuh warna","penyalahgunaan","peraturan","percaya diri","perhitungan","periang","peringatan","perjuangan","perlente","permintaan","persis","perspektif","pertama","pertama dalam sejarah","pertarungan","pertumpahan darah","pesimistis","pesta","petaka","pingsan","pintu belakang","plong","polarisasi","polos","populer","portofolio","pound","praktis","premi","privasi","privat","produktif","profesional","provokatif","psikologis","puas","pucat","pukulan","putus asa","racun","ragu","ragu-ragu","rahasia","rahasia dagang","raksasa","rakus","ramah","reaksi","reflektif","rekam jejak","rendah","rendahan","renjatan","rentan","resep","resmi","responsif","retas","revolusioner","ria","riang","rimbun","risau","riset","risiko","rumus","rusak","sabar","sadar","sadis","sah","sama sekali","samar","samar-samar","sangat bagus","sangat disarankan","sangat efektif","sangat menakjubkan","sangat menarik","sangsi","santai","saran","sarang telur","sarkastik","sayu","secara pengecut","sederhana","sedikit diketahui","segera","seharusnya","sehat","seimbang","sejati","sekarang","seks","seksi","selalu","selamanya","selaras","semalam","sembunyi","sempit","sempurna","semua termasuk","senang sekali","sengit","sensasionil","sentosa","sepenuhnya","seperti anak kecil","seram","serangan","sesegera","seumur hidup","siksa","siksaan","simpan","sinis","sinting","skandal","solusi","sombong","spektakuler","spesial","spoiler","spontan","stabil","stop","strategi","stres","studi","studi kasus","suci","suka hati","sukaria","sukses","sulap","sumber keuntungan","sungguh-sungguh","super","superior","surgawi","swasembada","syahwat","syur","tabah","tabu","tabungan","tabungan instan","tahan resesi","tajam","tak ayal","tak bersyarat","tak dikenal","tak kenal takut","tak tahu malu","tak terkendali","tak ternilai","tak tertandingi","takdir","takut","tamparan","tanda","tanpa beban","tanpa henti","tanpa ikatan","tanpa kewajiban","tanpa pertanyaan","tanpa rasa sakit","tanpa risiko","tanpa sadar","tanpa sensor","tanpa usaha","tantangan","tawa","tawar","tegang","teguh","teknologi","teknologi tinggi","telah ditinjau kembali","telanjang","telaten","teliti","tenang","tendang bokong","tenggelam","tenteram","tentu","tentunya","tepat","tepat waktu","tepi","terakhir","teramat","terang","terangkat","teratas","terbaik","terbaru","terbatas","terbebaskan","terbesar","terbongkar","terbuka","terbukti","tercela","tergeletak","terhormat","teriak","terima kasih","terinspirasi","terjamin","terjangkau","terjatuh","terjebak","terjerambab","terjun","terkejut","terkenal","terkesima","terkespos","terlalu","terlarang","terletak","terlindungi","terlupakan","termenung","termotivasi","terobsesi","teror","teroris","terpenting","terpenuhi","terperdaya","terperinci","terperosok","terpesona","terpilih","tersangkut","terselubung","tersembunyi","tersenyum","tertawa","tertekan","tertentu","tertinggal","tertutup","tetap","tiba-tiba","tidak baik","tidak berdaya","tidak berguna","tidak bisa dipungkiri","tidak bisa ditembus","tidak dapat dihentikan","tidak dipalsukan","tidak disiarkan","tidak handal","tidak kolot","tidak mampu","tidak masuk akal","tidak mengerti","tidak merasa aman","tidak nyaman","tidak past","tidak peduli","tidak pernah","tidak populer","tidak resmi","tidak responsif","tidak sabar","tidak sah","tidak seimbang","tidak sopan","tidak stabil","tidak tenang","tidak tepat","tidak terbatas","tidak terduga","tidak tergesa-gesa","tidak terkendali","tidak terlihat","tidak terlupakan","tidak tertandingi","tidak tertarik","tidak yakin","tidak-tidak","tidur","tingkatkan","tips","tolak","tolol","tragedi","tragis","transparansi","trauma","tren","trik","tripel","tulang belakang","tulang punggung","tulus","uang","uang kembali","ugal-ugalan","ulung","unduh","ungkapan","unik","untung","verifikasi","wabah","wahid","wahyu","wajib","waswas","wewenang","yakin"],"diacritics":{"A":"[\\u0041\\u24B6\\uFF21\\u00C0\\u00C1\\u00C2\\u1EA6\\u1EA4\\u1EAA\\u1EA8\\u00C3\\u0100\\u0102\\u1EB0\\u1EAE\\u1EB4\\u1EB2\\u0226\\u01E0\\u00C4\\u01DE\\u1EA2\\u00C5\\u01FA\\u01CD\\u0200\\u0202\\u1EA0\\u1EAC\\u1EB6\\u1E00\\u0104\\u023A\\u2C6F]","AA":"[\\uA732]","AE":"[\\u00C6\\u01FC\\u01E2]","AO":"[\\uA734]","AU":"[\\uA736]","AV":"[\\uA738\\uA73A]","AY":"[\\uA73C]","B":"[\\u0042\\u24B7\\uFF22\\u1E02\\u1E04\\u1E06\\u0243\\u0182\\u0181]","C":"[\\u0043\\u24B8\\uFF23\\u0106\\u0108\\u010A\\u010C\\u00C7\\u1E08\\u0187\\u023B\\uA73E]","D":"[\\u0044\\u24B9\\uFF24\\u1E0A\\u010E\\u1E0C\\u1E10\\u1E12\\u1E0E\\u0110\\u018B\\u018A\\u0189\\uA779]","DZ":"[\\u01F1\\u01C4]","Dz":"[\\u01F2\\u01C5]","E":"[\\u0045\\u24BA\\uFF25\\u00C8\\u00C9\\u00CA\\u1EC0\\u1EBE\\u1EC4\\u1EC2\\u1EBC\\u0112\\u1E14\\u1E16\\u0114\\u0116\\u00CB\\u1EBA\\u011A\\u0204\\u0206\\u1EB8\\u1EC6\\u0228\\u1E1C\\u0118\\u1E18\\u1E1A\\u0190\\u018E]","F":"[\\u0046\\u24BB\\uFF26\\u1E1E\\u0191\\uA77B]","G":"[\\u0047\\u24BC\\uFF27\\u01F4\\u011C\\u1E20\\u011E\\u0120\\u01E6\\u0122\\u01E4\\u0193\\uA7A0\\uA77D\\uA77E]","H":"[\\u0048\\u24BD\\uFF28\\u0124\\u1E22\\u1E26\\u021E\\u1E24\\u1E28\\u1E2A\\u0126\\u2C67\\u2C75\\uA78D]","I":"[\\u0049\\u24BE\\uFF29\\u00CC\\u00CD\\u00CE\\u0128\\u012A\\u012C\\u0130\\u00CF\\u1E2E\\u1EC8\\u01CF\\u0208\\u020A\\u1ECA\\u012E\\u1E2C\\u0197]","J":"[\\u004A\\u24BF\\uFF2A\\u0134\\u0248]","K":"[\\u004B\\u24C0\\uFF2B\\u1E30\\u01E8\\u1E32\\u0136\\u1E34\\u0198\\u2C69\\uA740\\uA742\\uA744\\uA7A2]","L":"[\\u004C\\u24C1\\uFF2C\\u013F\\u0139\\u013D\\u1E36\\u1E38\\u013B\\u1E3C\\u1E3A\\u0141\\u023D\\u2C62\\u2C60\\uA748\\uA746\\uA780]","LJ":"[\\u01C7]","Lj":"[\\u01C8]","M":"[\\u004D\\u24C2\\uFF2D\\u1E3E\\u1E40\\u1E42\\u2C6E\\u019C]","N":"[\\u004E\\u24C3\\uFF2E\\u01F8\\u0143\\u00D1\\u1E44\\u0147\\u1E46\\u0145\\u1E4A\\u1E48\\u0220\\u019D\\uA790\\uA7A4]","NJ":"[\\u01CA]","Nj":"[\\u01CB]","O":"[\\u004F\\u24C4\\uFF2F\\u00D2\\u00D3\\u00D4\\u1ED2\\u1ED0\\u1ED6\\u1ED4\\u00D5\\u1E4C\\u022C\\u1E4E\\u014C\\u1E50\\u1E52\\u014E\\u022E\\u0230\\u00D6\\u022A\\u1ECE\\u0150\\u01D1\\u020C\\u020E\\u01A0\\u1EDC\\u1EDA\\u1EE0\\u1EDE\\u1EE2\\u1ECC\\u1ED8\\u01EA\\u01EC\\u00D8\\u01FE\\u0186\\u019F\\uA74A\\uA74C]","OI":"[\\u01A2]","OO":"[\\uA74E]","OU":"[\\u0222]","P":"[\\u0050\\u24C5\\uFF30\\u1E54\\u1E56\\u01A4\\u2C63\\uA750\\uA752\\uA754]","Q":"[\\u0051\\u24C6\\uFF31\\uA756\\uA758\\u024A]","R":"[\\u0052\\u24C7\\uFF32\\u0154\\u1E58\\u0158\\u0210\\u0212\\u1E5A\\u1E5C\\u0156\\u1E5E\\u024C\\u2C64\\uA75A\\uA7A6\\uA782]","S":"[\\u0053\\u24C8\\uFF33\\u1E9E\\u015A\\u1E64\\u015C\\u1E60\\u0160\\u1E66\\u1E62\\u1E68\\u0218\\u015E\\u2C7E\\uA7A8\\uA784]","T":"[\\u0054\\u24C9\\uFF34\\u1E6A\\u0164\\u1E6C\\u021A\\u0162\\u1E70\\u1E6E\\u0166\\u01AC\\u01AE\\u023E\\uA786]","TZ":"[\\uA728]","U":"[\\u0055\\u24CA\\uFF35\\u00D9\\u00DA\\u00DB\\u0168\\u1E78\\u016A\\u1E7A\\u016C\\u00DC\\u01DB\\u01D7\\u01D5\\u01D9\\u1EE6\\u016E\\u0170\\u01D3\\u0214\\u0216\\u01AF\\u1EEA\\u1EE8\\u1EEE\\u1EEC\\u1EF0\\u1EE4\\u1E72\\u0172\\u1E76\\u1E74\\u0244]","V":"[\\u0056\\u24CB\\uFF36\\u1E7C\\u1E7E\\u01B2\\uA75E\\u0245]","VY":"[\\uA760]","W":"[\\u0057\\u24CC\\uFF37\\u1E80\\u1E82\\u0174\\u1E86\\u1E84\\u1E88\\u2C72]","X":"[\\u0058\\u24CD\\uFF38\\u1E8A\\u1E8C]","Y":"[\\u0059\\u24CE\\uFF39\\u1EF2\\u00DD\\u0176\\u1EF8\\u0232\\u1E8E\\u0178\\u1EF6\\u1EF4\\u01B3\\u024E\\u1EFE]","Z":"[\\u005A\\u24CF\\uFF3A\\u0179\\u1E90\\u017B\\u017D\\u1E92\\u1E94\\u01B5\\u0224\\u2C7F\\u2C6B\\uA762]","a":"[\\u0061\\u24D0\\uFF41\\u1E9A\\u00E0\\u00E1\\u00E2\\u1EA7\\u1EA5\\u1EAB\\u1EA9\\u00E3\\u0101\\u0103\\u1EB1\\u1EAF\\u1EB5\\u1EB3\\u0227\\u01E1\\u00E4\\u01DF\\u1EA3\\u00E5\\u01FB\\u01CE\\u0201\\u0203\\u1EA1\\u1EAD\\u1EB7\\u1E01\\u0105\\u2C65\\u0250]","aa":"[\\uA733]","ae":"[\\u00E6\\u01FD\\u01E3]","ao":"[\\uA735]","au":"[\\uA737]","av":"[\\uA739\\uA73B]","ay":"[\\uA73D]","b":"[\\u0062\\u24D1\\uFF42\\u1E03\\u1E05\\u1E07\\u0180\\u0183\\u0253]","c":"[\\u0063\\u24D2\\uFF43\\u0107\\u0109\\u010B\\u010D\\u00E7\\u1E09\\u0188\\u023C\\uA73F\\u2184]","d":"[\\u0064\\u24D3\\uFF44\\u1E0B\\u010F\\u1E0D\\u1E11\\u1E13\\u1E0F\\u0111\\u018C\\u0256\\u0257\\uA77A]","dz":"[\\u01F3\\u01C6]","e":"[\\u0065\\u24D4\\uFF45\\u00E8\\u00E9\\u00EA\\u1EC1\\u1EBF\\u1EC5\\u1EC3\\u1EBD\\u0113\\u1E15\\u1E17\\u0115\\u0117\\u00EB\\u1EBB\\u011B\\u0205\\u0207\\u1EB9\\u1EC7\\u0229\\u1E1D\\u0119\\u1E19\\u1E1B\\u0247\\u025B\\u01DD]","f":"[\\u0066\\u24D5\\uFF46\\u1E1F\\u0192\\uA77C]","g":"[\\u0067\\u24D6\\uFF47\\u01F5\\u011D\\u1E21\\u011F\\u0121\\u01E7\\u0123\\u01E5\\u0260\\uA7A1\\u1D79\\uA77F]","h":"[\\u0068\\u24D7\\uFF48\\u0125\\u1E23\\u1E27\\u021F\\u1E25\\u1E29\\u1E2B\\u1E96\\u0127\\u2C68\\u2C76\\u0265]","hv":"[\\u0195]","i":"[\\u0069\\u24D8\\uFF49\\u00EC\\u00ED\\u00EE\\u0129\\u012B\\u012D\\u00EF\\u1E2F\\u1EC9\\u01D0\\u0209\\u020B\\u1ECB\\u012F\\u1E2D\\u0268\\u0131]","j":"[\\u006A\\u24D9\\uFF4A\\u0135\\u01F0\\u0249]","k":"[\\u006B\\u24DA\\uFF4B\\u1E31\\u01E9\\u1E33\\u0137\\u1E35\\u0199\\u2C6A\\uA741\\uA743\\uA745\\uA7A3]","l":"[\\u006C\\u24DB\\uFF4C\\u0140\\u013A\\u013E\\u1E37\\u1E39\\u013C\\u1E3D\\u1E3B\\u017F\\u0142\\u019A\\u026B\\u2C61\\uA749\\uA781\\uA747]","lj":"[\\u01C9]","m":"[\\u006D\\u24DC\\uFF4D\\u1E3F\\u1E41\\u1E43\\u0271\\u026F]","n":"[\\u006E\\u24DD\\uFF4E\\u01F9\\u0144\\u00F1\\u1E45\\u0148\\u1E47\\u0146\\u1E4B\\u1E49\\u019E\\u0272\\u0149\\uA791\\uA7A5]","nj":"[\\u01CC]","o":"[\\u006F\\u24DE\\uFF4F\\u00F2\\u00F3\\u00F4\\u1ED3\\u1ED1\\u1ED7\\u1ED5\\u00F5\\u1E4D\\u022D\\u1E4F\\u014D\\u1E51\\u1E53\\u014F\\u022F\\u0231\\u00F6\\u022B\\u1ECF\\u0151\\u01D2\\u020D\\u020F\\u01A1\\u1EDD\\u1EDB\\u1EE1\\u1EDF\\u1EE3\\u1ECD\\u1ED9\\u01EB\\u01ED\\u00F8\\u01FF\\u0254\\uA74B\\uA74D\\u0275]","oi":"[\\u01A3]","ou":"[\\u0223]","oo":"[\\uA74F]","p":"[\\u0070\\u24DF\\uFF50\\u1E55\\u1E57\\u01A5\\u1D7D\\uA751\\uA753\\uA755]","q":"[\\u0071\\u24E0\\uFF51\\u024B\\uA757\\uA759]","r":"[\\u0072\\u24E1\\uFF52\\u0155\\u1E59\\u0159\\u0211\\u0213\\u1E5B\\u1E5D\\u0157\\u1E5F\\u024D\\u027D\\uA75B\\uA7A7\\uA783]","s":"[\\u0073\\u24E2\\uFF53\\u015B\\u1E65\\u015D\\u1E61\\u0161\\u1E67\\u1E63\\u1E69\\u0219\\u015F\\u023F\\uA7A9\\uA785\\u1E9B]","ss":"[\\u00DF]","t":"[\\u0074\\u24E3\\uFF54\\u1E6B\\u1E97\\u0165\\u1E6D\\u021B\\u0163\\u1E71\\u1E6F\\u0167\\u01AD\\u0288\\u2C66\\uA787]","tz":"[\\uA729]","u":"[\\u0075\\u24E4\\uFF55\\u00F9\\u00FA\\u00FB\\u0169\\u1E79\\u016B\\u1E7B\\u016D\\u00FC\\u01DC\\u01D8\\u01D6\\u01DA\\u1EE7\\u016F\\u0171\\u01D4\\u0215\\u0217\\u01B0\\u1EEB\\u1EE9\\u1EEF\\u1EED\\u1EF1\\u1EE5\\u1E73\\u0173\\u1E77\\u1E75\\u0289]","v":"[\\u0076\\u24E5\\uFF56\\u1E7D\\u1E7F\\u028B\\uA75F\\u028C]","vy":"[\\uA761]","w":"[\\u0077\\u24E6\\uFF57\\u1E81\\u1E83\\u0175\\u1E87\\u1E85\\u1E98\\u1E89\\u2C73]","x":"[\\u0078\\u24E7\\uFF58\\u1E8B\\u1E8D]","y":"[\\u0079\\u24E8\\uFF59\\u1EF3\\u00FD\\u0177\\u1EF9\\u0233\\u1E8F\\u00FF\\u1EF7\\u1E99\\u1EF5\\u01B4\\u024F\\u1EFF]","z":"[\\u007A\\u24E9\\uFF5A\\u017A\\u1E91\\u017C\\u017E\\u1E93\\u1E95\\u01B6\\u0225\\u0240\\u2C6C\\uA763]"},"researchesTests":["contentHasTOC","contentHasShortParagraphs","contentHasAssets","keywordInTitle","keywordInMetaDescription","keywordInPermalink","keywordIn10Percent","keywordInContent","keywordInSubheadings","keywordInImageAlt","keywordDensity","keywordNotUsed","lengthContent","lengthPermalink","linksHasInternal","linksHasExternals","linksNotAllExternals","titleStartWithKeyword","titleSentiment","titleHasPowerWords","titleHasNumber","hasContentAI"],"hasRedirection":false,"hasBreadcrumb":false},"homeUrl":"https:\/\/ocr365.com\/id","objectID":712,"objectType":"post","locale":"id","localeFull":"id_ID","overlayImages":{"play":{"name":"Ikon Putar","url":"https:\/\/ocr365.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-play.png","path":"\/var\/www\/vhosts\/ocr365.com\/httpdocs\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-play.png","position":"middle_center"},"gif":{"name":"Ikon GIF","url":"https:\/\/ocr365.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-gif.png","path":"\/var\/www\/vhosts\/ocr365.com\/httpdocs\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-gif.png","position":"middle_center"}},"defautOgImage":"https:\/\/ocr365.com\/wp-content\/uploads\/2025\/01\/LOGO8.png","customPermalinks":true,"isUserRegistered":false,"autoSuggestKeywords":false,"connectSiteUrl":"https:\/\/rankmath.com\/auth?site=https%3A%2F%2Focr365.com%2Fid&r=https%3A%2F%2Focr365.com%2Fid%2Fwp-json%2Fwp%2Fv2%2Fpages%2F712%3Fnonce%3D2c49548879","maxTags":5,"trendsIcon":"<svg viewBox=\"0 0 610 610\"><path d=\"M18.85,446,174.32,290.48l58.08,58.08L76.93,504a14.54,14.54,0,0,1-20.55,0L18.83,466.48a14.54,14.54,0,0,1,0-20.55Z\" style=\"fill:#4285f4\"\/><path d=\"M242.65,242.66,377.59,377.6l-47.75,47.75a14.54,14.54,0,0,1-20.55,0L174.37,290.43l47.75-47.75A14.52,14.52,0,0,1,242.65,242.66Z\" style=\"fill:#ea4335\"\/><polygon points=\"319.53 319.53 479.26 159.8 537.34 217.88 377.61 377.62 319.53 319.53\" style=\"fill:#fabb05\"\/><path d=\"M594.26,262.73V118.61h0a16.94,16.94,0,0,0-16.94-16.94H433.2a16.94,16.94,0,0,0-12,28.92L565.34,274.71h0a16.94,16.94,0,0,0,28.92-12Z\" style=\"fill:#34a853\"\/><rect width=\"610\" height=\"610\" style=\"fill:none\"\/><\/svg>","showScore":true,"siteFavIcon":"https:\/\/ocr365.com\/wp-content\/uploads\/2025\/01\/cropped-512-32x32.png","canUser":{"general":false,"advanced":false,"snippet":false,"social":false,"analysis":false,"analytics":false,"content_ai":false},"showKeywordIntent":true,"isPro":false,"is_front_page":false,"trendsUpgradeLink":"https:\/\/rankmath.com\/pricing\/?utm_source=Plugin&utm_medium=CE%20General%20Tab%20Trends&utm_campaign=WP","trendsUpgradeLabel":"Upgrade","trendsPreviewImage":"https:\/\/ocr365.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/trends-preview.jpg","currentEditor":false,"homepageData":{"assessor":{"powerWords":["abadi","absolut","agenda rahasia","agresif","ahli","ahmak","ajaib","aktif","akui","alamiah","alur rahasia","aman","aneh","anggaran","anggun","angkuh","animasi","animo","anonim","anti gagal","antusias","apakah anda tahu","argumentatif","asing","asli","asusila","asyik","autentik","awas","ayem","aziz","azmat","badai","badut","bagaimana cara","bagi hadiah","bahagia","bahaya","balas dendam","banget","bangsat","bantahan","banter","banyak akal","baru","baru saja tiba","batalkan kapan saja","batas waktu","batu sandungan","bawah tanah","bebas rasa bersalah","bejat","beli","belum dimanfaatkan","belum pernah terjadi","benar-benar","bencana alam","benci","beneran","bengis","bengkok","beracun","berahi","berani","berapi","berbahagia","berbahaya","berbakti","berbisa","berdarah","berdarah dingin","berdosa","berfokus","bergeliat","bergelombang","berguna","berharap","berharga","berhasil","berhasrat","berhawa-nafsu","berisiko","berjiwa","berkedut","berkelakar","berkembang","berkeringat","berkesan","berkuasa","berkurang","berlimpah","bermanfaat","bermusuhan","berpusat","bersandaran","bersemangat","berseri","berseri-seri","bersertifikat","berseteru","bersih","bersinar","bersorak","bersyukur","bertahan","bertahan hidup","bertambah","bertanggung jawab","bertarung","bertenaga","berterimakasih","bertumbuh","beruap","berubah","berwenang","besar","besar-besaran","bikin emosi","bikin malu","bikin mual","bikin ngiler","bimbang","binal","bingung","bisa beradaptasi","bocoran","bodoh","bohong","bokek","bom","bombardir","bonus","boros","brutal","buas","budak","bui","bukan main","buntut","bunuh","buruan","busuk","busung","buta","cabul","cahaya","cairan","cambuk","canggung","cantik","caruk","cekatan","cemerlang","cengis","cepat","cerah","cerdas","cerewet","ceroboh","cinta","congkak","contekan","contoh","cukup","cukup besar","cukupan","curang","curiga","daftar hitam","dahsyat","daif","dalam","dalam waktu dekat","dapat diandalkan","dapat dikembalikan","dapat ditindaklanjuti","darurat","dasar","daya ingat","definitif","deg-degan","demoralisasi","denda","dendam","dengan cepat","dengan mudah","dengan sedih","dengan serius","derita","detik akhir","di bawah harga","di dalam zona","di sini","diakui","diam","diancam","diasingkan","dibalik layar","diberdayakan","diberkati","dibodohi","dibunuh","dicari","dicatat","dicekok","didiagnosis","didukung","dihukum","dilanggar","dilarang","dilepaskan","dimainkan","dimarahi","dinamis","dipecat","dipercaya","disampaikan","disayangkan","disederhanakan","diselundupkan","disensor","disetujui","diskon","disokong","ditahan","ditandai","ditargetkan","dites","ditipu","diwajibkan","dobel","dokumen","dolar","dominasi","dorongan","dosa","dosa-dosa","durjana","edan","edukatif","efektif","efisien","ekonomis","eksklusif","eksplosif","ekstra","elite","elok","enam angka","eneq","energi","energik","enteng","epidemis","epik","etis","euforia","fantasi","final","fokus","frustrasi","fundamental","gaduh","gagah","gagal","gagal total","gaib","gairah","galak","gampang","ganjil","garang","gasang","gawat","gede","gelap","geli","gelisah","gelora","gembira","gemetar","gengsi","geram","gila","gila hormat","glamor","goblok","godaan","gratis","gravitasi","grogi","gugatan","gugup","gundah","gusar","hadiah","hak istimewa","hakekat","hancur","haram","harapan","harfiah","harga","harga diri","hari ini","hari penghakiman","harta","harus","hasil","hati","hebat","heboh","hemat","hidup","hina","hingar-bingar","hipnosis","hipnotik","hiruk-pikuk","hoaks","hoax","horor","humor","idiot","ilusif","imajinasi","iman","indah","informatif","inkonvensional","inovatif","inspirasi","intel","intens","interesan","intinya","invasi","investasi","iri","irs","istirahat","jackpot","jagoan","jagur","jahat","jahil","jarang","jatuh","jebakan","jelek","jeles","jelimet","jenazah","jengkel","jenius","jijik","jinak","jorok","jubilant","judi","jujur","kacau","kado","kaget","kalah","kasar","kaya","keahlian","keajaiban","keamanan","kebahagiaan","kebaruan","kebebasan","kebenaran","keberanian","kebesaran","kebiadaban","kebohongan","kecanggungan","kecantikan","kecerobohan","kecewa","kedahsyatan","keeksklusifan","kegagahan","kegagalan","kegembiraan","kegigihan","kegirangan","kehilangan","kejam","kejelasan","kejut","kejutan","kejutkan","kekalahan","kekeliruan","kekosenan","kekurangan","kelancangan","kelas master","kelengkapan","kelimpungan","keluhuran","kemaruk","kematian","kemelaratan","kemenangan","kenalan","kengerian","kentara","kepeloporan","kepercayaan","keperkasaan","keracak","kerakusan","keramahan","keras","keras kepala","keringat","kesakitan","kesalahan","kesederhanaan","kesedihan","keselamatan","kesempatan terakhir","kesepian","ketakutan","keteguhan hati","ketekunan","keterlaluan","ketidakberdayaan","ketidaksabaran","keunggulan","keuntungan","kewalahan","keyakinan","khidmat","kiamat","kiat","kickstart","kikuk","kokoh","kolosal","kompetitif","komprehensif","kompromi","konfidensi","konstruktif","kontan","kontroversi","konyol","kooperatif","kopi","korban","korupsi","kotor","kreatif","krisis","kritis","kualitas","kuat","kuno","kurang ajar","kurang dimanfaatkan","kusut","kw","laba","langka","langkah","langsung","laporan","larangan","lawan","lebih bagus","lebih baik","ledakan","lega","legendaris","lelah","lemah","lengkap","lezat","liar","liberal","licik","licin","lihai","limbah","lincah","lipat empat","lonjakan","luar biasa","lucu","luka berat","lumpuh","luwes","mabuk","mahal","mainstream","makarya","makmur","mala","malapetaka","malas","malu","mampu","manipulatif","manis sekali","manjur","mantul","manusia super","mara","marah","masalah","masif","masih","master","mata duitan","mati","mati kutu","mayat","megah","melayang","meledak","meleleh","melena","melepaskan","meletus","melindungi","melongo","melonjak","melontarkan","melumpuhkan","meluncurkan","memaafkan","memalukan","mematikan","membakar","membalas","membandingkan","membenci diri sendiri","memberontak","membinasakan","membocorkan","membuat","membuat ulang","membubung","membuka mata","membunuh","memenuhi","memerah","memetik","memikat","memikat hati","memilukan","memperberat","memperdaya","memperkenalkan","mempermalukan","mempesona","mempesonakan","memprovokasi","memromosikan","memuakkan","memukau","memukul","memusnahkan","memvalidasi","menakjubkan","menakuntukan","menakuti","menakutkan","menang","menangis","menantang","menarik","menawan","mencapai","mencegah","mencekik","mencengkeram","mencolok","mencuri","mencurigakan","mendalam","mendebarkan","menderita","mendesak","mendobrak","mendukung","menegur","menekankan","menemukan","menendang","menentang","menewaskan","mengagumkan","mengaku","mengakui","mengalahkan","mengancam","mengangkat","menganiaya","mengatasi","mengejuntukan","mengeksploitasi","mengerikan","mengerti","mengesankan","mengetahui semua","menggelisahkan","menggemparkan","menggenjot","menggerakkan","menggertakkan","menggilas","menggoda","menghancurkan","menghapuskan","mengharukan","menghebohkan","mengherankan","menghina","menghukum","mengibuli","mengidam","mengigau","menginspirasi","mengintai","mengintimidasi","menguangkan","menguap","menguasai","mengubah","mengubah hidup","mengulangi","mengumumkan","mengungkap","mengungkapkan","menguntungkan","mengutuk","meningkatkan","menipu","menjanjikan","menjerumuskan","menjijikkan","menjilat","menjulang","menolak","menuduh","menundukkan","menunggu","menusuk dari belakang","menutupi","menyabotase","menyakitkan","menyalakan","menyarankan","menyayat","menyelundupkan","menyemangati","menyeramkan","menyerang","menyetujui","menyihir","menyiksa","menyilaukan","menyogok","menyolok","menyoroti","menyuap","meracuni","merangsang","merayu","merebut","merendahkan","merenungkan","meriah","meroket","merosot","merugikan","mewah","meyakinkan","milik","milyar","mimpi buruk","minat","minimalis","miskin","misteri","molek","muak","mudah","mudah dipahami","mulai cepat","mulia","muncul","mungkin","murah","nafsu","naik pitam","naim","nakal","nanah","nasib","nazi","neraka","ngaco","ngakak","ngeri","ngiler","nilai","niscaya","nol rupiah","nyaman","obral","obsesi","oke","omong kosong","optimis","optimistis","orang bodoh","orang dalam","orang gila","orisinil","padat","pahala","pahlawan","paling besar","paling dahsyat","paling efektif","paling lucu","palsu","pandir","panik","parah","pasar gelap","pasti","pastinya","pastinya paling rendah","patut diperhatikan","pecah","pecinta kesenangan","pecundang","pedih","peka","pelanggaran","peluang","peluncuran","pembantaian","pembunuhan","pemecahan","pemicu","pemula","penaklukan","pendendam","pendengki","penemuan","penerobosan","pengakuan","pengecut","pengembalian","pengembalian dana","penghakiman","penghancuran","penghinaan","pengungsi","penipu","penipuan","penjahat","penjara","penjualan terbaik","penting","penuh","penuh dosa","penuh kepercayaan","penuh warna","penyalahgunaan","peraturan","percaya diri","perhitungan","periang","peringatan","perjuangan","perlente","permintaan","persis","perspektif","pertama","pertama dalam sejarah","pertarungan","pertumpahan darah","pesimistis","pesta","petaka","pingsan","pintu belakang","plong","polarisasi","polos","populer","portofolio","pound","praktis","premi","privasi","privat","produktif","profesional","provokatif","psikologis","puas","pucat","pukulan","putus asa","racun","ragu","ragu-ragu","rahasia","rahasia dagang","raksasa","rakus","ramah","reaksi","reflektif","rekam jejak","rendah","rendahan","renjatan","rentan","resep","resmi","responsif","retas","revolusioner","ria","riang","rimbun","risau","riset","risiko","rumus","rusak","sabar","sadar","sadis","sah","sama sekali","samar","samar-samar","sangat bagus","sangat disarankan","sangat efektif","sangat menakjubkan","sangat menarik","sangsi","santai","saran","sarang telur","sarkastik","sayu","secara pengecut","sederhana","sedikit diketahui","segera","seharusnya","sehat","seimbang","sejati","sekarang","seks","seksi","selalu","selamanya","selaras","semalam","sembunyi","sempit","sempurna","semua termasuk","senang sekali","sengit","sensasionil","sentosa","sepenuhnya","seperti anak kecil","seram","serangan","sesegera","seumur hidup","siksa","siksaan","simpan","sinis","sinting","skandal","solusi","sombong","spektakuler","spesial","spoiler","spontan","stabil","stop","strategi","stres","studi","studi kasus","suci","suka hati","sukaria","sukses","sulap","sumber keuntungan","sungguh-sungguh","super","superior","surgawi","swasembada","syahwat","syur","tabah","tabu","tabungan","tabungan instan","tahan resesi","tajam","tak ayal","tak bersyarat","tak dikenal","tak kenal takut","tak tahu malu","tak terkendali","tak ternilai","tak tertandingi","takdir","takut","tamparan","tanda","tanpa beban","tanpa henti","tanpa ikatan","tanpa kewajiban","tanpa pertanyaan","tanpa rasa sakit","tanpa risiko","tanpa sadar","tanpa sensor","tanpa usaha","tantangan","tawa","tawar","tegang","teguh","teknologi","teknologi tinggi","telah ditinjau kembali","telanjang","telaten","teliti","tenang","tendang bokong","tenggelam","tenteram","tentu","tentunya","tepat","tepat waktu","tepi","terakhir","teramat","terang","terangkat","teratas","terbaik","terbaru","terbatas","terbebaskan","terbesar","terbongkar","terbuka","terbukti","tercela","tergeletak","terhormat","teriak","terima kasih","terinspirasi","terjamin","terjangkau","terjatuh","terjebak","terjerambab","terjun","terkejut","terkenal","terkesima","terkespos","terlalu","terlarang","terletak","terlindungi","terlupakan","termenung","termotivasi","terobsesi","teror","teroris","terpenting","terpenuhi","terperdaya","terperinci","terperosok","terpesona","terpilih","tersangkut","terselubung","tersembunyi","tersenyum","tertawa","tertekan","tertentu","tertinggal","tertutup","tetap","tiba-tiba","tidak baik","tidak berdaya","tidak berguna","tidak bisa dipungkiri","tidak bisa ditembus","tidak dapat dihentikan","tidak dipalsukan","tidak disiarkan","tidak handal","tidak kolot","tidak mampu","tidak masuk akal","tidak mengerti","tidak merasa aman","tidak nyaman","tidak past","tidak peduli","tidak pernah","tidak populer","tidak resmi","tidak responsif","tidak sabar","tidak sah","tidak seimbang","tidak sopan","tidak stabil","tidak tenang","tidak tepat","tidak terbatas","tidak terduga","tidak tergesa-gesa","tidak terkendali","tidak terlihat","tidak terlupakan","tidak tertandingi","tidak tertarik","tidak yakin","tidak-tidak","tidur","tingkatkan","tips","tolak","tolol","tragedi","tragis","transparansi","trauma","tren","trik","tripel","tulang belakang","tulang punggung","tulus","uang","uang kembali","ugal-ugalan","ulung","unduh","ungkapan","unik","untung","verifikasi","wabah","wahid","wahyu","wajib","waswas","wewenang","yakin"],"diacritics":true,"researchesTests":["contentHasTOC","contentHasShortParagraphs","contentHasAssets","keywordInTitle","keywordInMetaDescription","keywordInPermalink","keywordIn10Percent","keywordInContent","keywordInSubheadings","keywordInImageAlt","keywordDensity","keywordNotUsed","lengthContent","lengthPermalink","linksHasInternal","linksHasExternals","linksNotAllExternals","titleStartWithKeyword","titleSentiment","titleHasPowerWords","titleHasNumber","hasContentAI"],"hasBreadcrumb":false,"serpData":{"title":"%sitename% %page% %sep% %sitedesc%","description":"","titleTemplate":"%sitename% %page% %sep% %sitedesc%","descriptionTemplate":"","focusKeywords":"","breadcrumbTitle":"Home","robots":{"index":true},"advancedRobots":{"max-snippet":"-1","max-video-preview":"-1","max-image-preview":"large"},"facebookTitle":"","facebookDescription":"","facebookImage":"","facebookImageID":""}}},"tocTitle":"Table of Contents","tocExcludeHeadings":[],"listStyle":"ul"},"_links":{"self":[{"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/pages\/712","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/comments?post=712"}],"version-history":[{"count":31,"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/pages\/712\/revisions"}],"predecessor-version":[{"id":1630,"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/pages\/712\/revisions\/1630"}],"wp:attachment":[{"href":"https:\/\/ocr365.com\/id\/wp-json\/wp\/v2\/media?parent=712"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}