Skip to content

Commit

Permalink
Merge pull request #2 from Open-WP-Club/v0.0.1.1
Browse files Browse the repository at this point in the history
V0.0.2
  • Loading branch information
MrGKanev authored Sep 4, 2024
2 parents 10c14a6 + a40d5f0 commit e3a97fa
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 69 deletions.
155 changes: 114 additions & 41 deletions js/diagram.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jQuery(document).ready(function ($) {
});

var contentRelationshipMapData = ailAjax.savedDiagram || null;
var internalLinkAnalysisData = ailAjax.savedInternalLinkAnalysis || null;

// Load saved content relationship map if it exists
if (contentRelationshipMapData) {
Expand All @@ -21,6 +22,11 @@ jQuery(document).ready(function ($) {
$("#delete-diagram, #download-diagram, #download-svg").show();
}

// Load saved internal link analysis if it exists
if (internalLinkAnalysisData) {
initializeInternalLinkAnalysis();
}

$("#generate-diagram").on("click", function (e) {
e.preventDefault();
var $button = $(this);
Expand Down Expand Up @@ -116,52 +122,28 @@ jQuery(document).ready(function ($) {

$("#download-diagram").on("click", function (e) {
e.preventDefault();
downloadDiagram("png");
downloadDiagram("png", "content-relationship-map");
});

$("#download-svg").on("click", function (e) {
e.preventDefault();
downloadDiagram("svg");
downloadDiagram("svg", "content-relationship-map");
});

function downloadDiagram(format) {
var $diagram = $("#content-relationship-map svg");
if ($diagram.length) {
var svgData = new XMLSerializer().serializeToString($diagram[0]);
if (format === "svg") {
var blob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
saveAs(blob, "content_relationship_map.svg");
} else {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
canvas.toBlob(function (blob) {
saveAs(blob, "content_relationship_map.png");
});
};
img.src =
"data:image/svg+xml;base64," +
btoa(unescape(encodeURIComponent(svgData)));
}
} else {
alert("No map to download. Please generate a map first.");
}
}

// Internal Link Analysis
$("#analyze-internal-links").on("click", function (e) {
e.preventDefault();
var $button = $(this);
var $results = $("#internal-link-analysis-results");
var buttonText = internalLinkAnalysisData ? "Updating..." : "Analyzing...";

$button.prop("disabled", true).text("Analyzing...");
$results.html(
"<p>Analysis in progress. This may take a few moments...</p>"
);
$button.prop("disabled", true).text(buttonText);

if (!internalLinkAnalysisData) {
$results.html(
"<p>Analysis in progress. This may take a few moments...</p>"
);
}

$.ajax({
url: ailAjax.ajaxurl,
Expand All @@ -171,7 +153,11 @@ jQuery(document).ready(function ($) {
},
success: function (response) {
if (response.success) {
renderInternalLinkDiagram(response.data);
internalLinkAnalysisData = response.data;
renderInternalLinkAnalysis();
$(
"#delete-internal-link-analysis, #download-internal-link-analysis, #download-internal-link-analysis-svg"
).show();
} else {
$results.html(
"<p>Failed to analyze internal links. Please try again.</p>"
Expand All @@ -184,25 +170,112 @@ jQuery(document).ready(function ($) {
);
},
complete: function () {
$button.prop("disabled", false).text("Analyze Internal Links");
$button.prop("disabled", false).text("Update Analysis");
},
});
});

function renderInternalLinkDiagram(diagramData) {
function initializeInternalLinkAnalysis() {
renderInternalLinkAnalysis();
$("#analyze-internal-links").text("Update Analysis");
$(
"#delete-internal-link-analysis, #download-internal-link-analysis, #download-internal-link-analysis-svg"
).show();
}

function renderInternalLinkAnalysis() {
var $results = $("#internal-link-analysis-results");
$results.empty();
var diagramContainer = $('<div class="mermaid">').text(diagramData);
var diagramContainer = $('<div class="mermaid">').text(
internalLinkAnalysisData
);
$results.append(diagramContainer);
try {
mermaid.init(undefined, $(".mermaid"));
} catch (error) {
console.error("Mermaid rendering error:", error);
console.log("Diagram data:", diagramData);
console.log("Diagram data:", internalLinkAnalysisData);
$results.html(
"<p>Failed to render internal link diagram. The data might be too complex or contain invalid syntax.</p>"
"<p>Failed to render internal link analysis. The data might be too complex or contain invalid syntax. Please try again with fewer content items.</p>"
);
$results.append("<pre>" + diagramData + "</pre>");
$results.append("<pre>" + internalLinkAnalysisData + "</pre>");
}
}

$("#delete-internal-link-analysis").on("click", function (e) {
e.preventDefault();
var $button = $(this);
$button.prop("disabled", true).text("Deleting...");

$.ajax({
url: ailAjax.ajaxurl,
type: "POST",
data: {
action: "delete_internal_link_analysis",
},
success: function (response) {
if (response.success) {
var $results = $("#internal-link-analysis-results");
$results.empty();
internalLinkAnalysisData = null;
$("#analyze-internal-links").text("Analyze Internal Links");
$(
"#delete-internal-link-analysis, #download-internal-link-analysis, #download-internal-link-analysis-svg"
).hide();
} else {
alert("Failed to delete the analysis. Please try again.");
}
},
error: function () {
alert(
"An error occurred while deleting the analysis. Please try again."
);
},
complete: function () {
$button.prop("disabled", false).text("Delete Analysis");
},
});
});

$("#download-internal-link-analysis").on("click", function (e) {
e.preventDefault();
downloadDiagram("png", "internal-link-analysis");
});

$("#download-internal-link-analysis-svg").on("click", function (e) {
e.preventDefault();
downloadDiagram("svg", "internal-link-analysis");
});

function downloadDiagram(format, diagramType) {
var $diagram =
diagramType === "content-relationship-map"
? $("#content-relationship-map svg")
: $("#internal-link-analysis-results svg");

if ($diagram.length) {
var svgData = new XMLSerializer().serializeToString($diagram[0]);
if (format === "svg") {
var blob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
saveAs(blob, diagramType + ".svg");
} else {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
canvas.toBlob(function (blob) {
saveAs(blob, diagramType + ".png");
});
};
img.src =
"data:image/svg+xml;base64," +
btoa(unescape(encodeURIComponent(svgData)));
}
} else {
alert("No diagram to download. Please generate a diagram first.");
}
}

Expand Down
74 changes: 46 additions & 28 deletions wp-internal-linking.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: WordPress Internal Linking
* Plugin URI: https://github.com/Open-WP-Club/wp-internal-linking
* Description: A plugin to manage and analyze internal linking in WordPress
* Version: 0.0.2
* Version: 0.0.3
* Author: Gabriel Kanev
* Author URI: https://gkanev.com
* License: GPL-2.0 License
Expand Down Expand Up @@ -34,6 +34,7 @@ public function __construct()
add_action('wp_ajax_delete_content_relationship_map', array($this, 'delete_content_relationship_map'));
add_action('wp_ajax_analyze_all_content', array($this, 'analyze_all_content'));
add_action('wp_ajax_analyze_internal_links', array($this, 'analyze_internal_links'));
add_action('wp_ajax_delete_internal_link_analysis', array($this, 'delete_internal_link_analysis'));

$this->options = get_option('internal_linking_options');
$this->blacklist = $this->get_blacklist();
Expand All @@ -54,7 +55,7 @@ public function add_plugin_pages()

public function create_main_page()
{
?>
?>
<div class="wrap">
<h1>Internal Linking</h1>
<h2 class="nav-tab-wrapper">
Expand Down Expand Up @@ -141,7 +142,7 @@ public function create_overview_page()
</tbody>
</table>
</div>

<div class="internal-linking-section">
<h3>Manage Blacklist</h3>
<div id="blacklist-manager">
Expand Down Expand Up @@ -209,10 +210,15 @@ public function create_internal_link_analysis_page()
<div class="internal-linking-section">
<h3>Internal Link Analysis</h3>
<p>Analyze existing internal links in your posts, pages, and other content types.</p>
<button id="analyze-internal-links" class="button button-primary">Analyze Internal Links</button>
<div id="internal-link-analysis-results"></div>
<div id="internal-link-analysis-results" data-saved-analysis="<?php echo esc_attr($saved_analysis ? 'true' : 'false'); ?>"></div>
<div class="button-group">
<button id="analyze-internal-links" class="button button-primary"><?php echo $saved_analysis ? 'Update Analysis' : 'Analyze Internal Links'; ?></button>
<button id="delete-internal-link-analysis" class="button" <?php echo $saved_analysis ? '' : 'style="display:none;"'; ?>>Delete Analysis</button>
<button id="download-internal-link-analysis" class="button" <?php echo $saved_analysis ? '' : 'style="display:none;"'; ?>>Download as PNG</button>
<button id="download-internal-link-analysis-svg" class="button" <?php echo $saved_analysis ? '' : 'style="display:none;"'; ?>>Download as SVG</button>
</div>
</div>
<?php
<?php
}

public function page_init()
Expand All @@ -239,7 +245,8 @@ public function enqueue_admin_scripts($hook)
wp_enqueue_script('internal-linking-diagram', plugins_url('js/diagram.js', __FILE__), array('jquery', 'mermaid', 'file-saver'), '1.0', true);
wp_localize_script('internal-linking-admin', 'ailAjax', array(
'ajaxurl' => admin_url('admin-ajax.php'),
'savedDiagram' => get_option('internal_linking_diagram', '')
'savedDiagram' => get_option('internal_linking_diagram', ''),
'savedInternalLinkAnalysis' => get_option('internal_linking_analysis_diagram', '')
));
}
}
Expand All @@ -257,8 +264,8 @@ private function display_blacklist()
{
$page = isset($_GET['blacklist_page']) ? intval($_GET['blacklist_page']) : 1;
$search = isset($_GET['blacklist_search']) ? sanitize_text_field($_GET['blacklist_search']) : '';
$filtered_blacklist = array_filter($this->blacklist, function($word) use ($search) {

$filtered_blacklist = array_filter($this->blacklist, function ($word) use ($search) {
return empty($search) || stripos($word, $search) !== false;
});

Expand All @@ -283,8 +290,8 @@ private function display_blacklist_pagination()
{
$page = isset($_GET['blacklist_page']) ? intval($_GET['blacklist_page']) : 1;
$search = isset($_GET['blacklist_search']) ? sanitize_text_field($_GET['blacklist_search']) : '';
$filtered_blacklist = array_filter($this->blacklist, function($word) use ($search) {

$filtered_blacklist = array_filter($this->blacklist, function ($word) use ($search) {
return empty($search) || stripos($word, $search) !== false;
});

Expand Down Expand Up @@ -511,21 +518,6 @@ public function delete_content_relationship_map()
wp_send_json_success();
}

private function escape_mermaid_label($text)
{
// Remove HTML entities
$text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// Remove any characters that might interfere with Mermaid syntax
$text = preg_replace('/[\\\\\'\"]/u', '', $text);
// Limit length to prevent overly long labels
$text = mb_substr($text, 0, 30);
if (mb_strlen($text) >= 30) {
$text .= '...';
}
// Ensure the label is not empty
return !empty($text) ? $text : 'Unnamed';
}

public function analyze_internal_links()
{
if (!current_user_can('manage_options')) {
Expand Down Expand Up @@ -571,9 +563,20 @@ public function analyze_internal_links()
wp_reset_postdata();

$diagram = $this->generate_internal_link_diagram($link_data);
update_option('internal_linking_analysis_diagram', $diagram);
wp_send_json_success($diagram);
}

public function delete_internal_link_analysis()
{
if (!current_user_can('manage_options')) {
wp_die('Unauthorized user');
}

delete_option('internal_linking_analysis_diagram');
wp_send_json_success();
}

private function generate_internal_link_diagram($link_data)
{
$diagram = "graph TD\n";
Expand Down Expand Up @@ -605,6 +608,21 @@ private function generate_internal_link_diagram($link_data)
return $diagram;
}

private function escape_mermaid_label($text)
{
// Remove HTML entities
$text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// Remove any characters that might interfere with Mermaid syntax
$text = preg_replace('/[\\\\\'\"]/u', '', $text);
// Limit length to prevent overly long labels
$text = mb_substr($text, 0, 30);
if (mb_strlen($text) >= 30) {
$text .= '...';
}
// Ensure the label is not empty
return !empty($text) ? $text : 'Unnamed';
}

public function add_ajax_handlers()
{
add_action('wp_ajax_add_blacklist_word', array($this, 'ajax_add_blacklist_word'));
Expand Down Expand Up @@ -654,7 +672,7 @@ public function ajax_search_blacklist()
$search = isset($_POST['search']) ? sanitize_text_field($_POST['search']) : '';
$page = isset($_POST['page']) ? intval($_POST['page']) : 1;

$filtered_blacklist = array_filter($this->blacklist, function($word) use ($search) {
$filtered_blacklist = array_filter($this->blacklist, function ($word) use ($search) {
return empty($search) || stripos($word, $search) !== false;
});

Expand Down Expand Up @@ -701,4 +719,4 @@ function run_internal_linking()
}

// Hook to WordPress init action
add_action('init', 'run_internal_linking');
add_action('init', 'run_internal_linking');

0 comments on commit e3a97fa

Please sign in to comment.