diff --git a/README.txt b/README.txt
index 9346640..474db25 100644
--- a/README.txt
+++ b/README.txt
@@ -18,6 +18,7 @@ Basic usage
 * Theme : theme_name.theme eg. zen.theme
 * Translation : name.translation eg. fr.translation
 * Installation profile : name.installprofile eg. uberDrupal.installprofile
+* Issue on Drupal.org : node_id.issue eg. 345196.nid
 * Node on Drupal.org : node_id.do eg. 345196.nid
 * Node on groups.drupal.org : node_id.gdo eg. 345196.gdo
 * Users : user_id.user eg. 48488.user
\ No newline at end of file
diff --git a/dopl.css b/dopl.css
new file mode 100644
index 0000000..97da83c
--- /dev/null
+++ b/dopl.css
@@ -0,0 +1,33 @@
+
+.project-issue-status-info a, .project-issue-status-info .project-issue-assigned-user {
+  background-color: #CDCDCD;
+  border-radius: 4px 4px 4px 4px;
+  padding: 2px 4px;
+}
+.project-issue-status-info .project-issue-assigned-user {
+  white-space: nowrap;
+}
+.project-issue-status-1 a {
+  background-color: #FFFFFF;
+}
+.project-issue-status-2 a {
+  background-color: #C0FFC0;
+}
+.project-issue-status-3 a, .project-issue-status-4 a, .project-issue-status-5 a, .project-issue-status-6 a {
+  background-color: #DDDDFF;
+}
+.project-issue-status-7 a {
+  background-color: #FFC9C9;
+}
+.project-issue-status-8 a {
+    background-color: #FFFFDD;
+}
+.project-issue-status-13 a {
+  background-color: #FFE7DD;
+}
+.project-issue-status-14 a {
+  background-color: #E7FFDD;
+}
+.project-issue-status-2, .project-issue-status-3, .project-issue-status-5, .project-issue-status-6, .project-issue-status-7 {
+  text-decoration: line-through;
+}
diff --git a/dopl.module b/dopl.module
index 9a82524..8783d9f 100644
--- a/dopl.module
+++ b/dopl.module
@@ -17,6 +17,13 @@ function dopl_help($path, $arg) {
 }
 
 /**
+ * Implementation of hook_init()
+ */
+function dopl_init() {
+  drupal_add_css(drupal_get_path('module', 'dopl') . '/dopl.css');
+}
+
+/**
  * Implementation of hook_filter_info()
  */
 function dopl_filter_info() {
@@ -32,7 +39,7 @@ function dopl_filter_info() {
 
 
 function _dopl_filter_tips($delta, $format, $long = FALSE) {
-  return t('Use one of the forms <em>name.module</em>, <em>name.theme</em>, <em>name.translation</em>, <em>name.installprofile</em> or <em>name.project</em>, in order to link to <em>http://drupal.org/project/name</em> - Note that a link will be generated even if the project or node does not exist.<br />Use <em>[nid].do</em> to link to <em>http://drupal.org/node/[nid]</em>, and <em>[nid].gdo</em> to link to <em>http://groups.drupal.org/node/[nid]</em> - Links will only be generated for valid node IDs using this format.');
+  return t('Use one of the forms <em>name.module</em>, <em>name.theme</em>, <em>name.translation</em>, <em>name.installprofile</em> or <em>name.project</em>, in order to link to <em>http://drupal.org/project/name</em> - Note that a link will be generated even if the project or node does not exist.<br />Use <em>[nid].do</em> or <em>[nid].issue</em> to link to <em>http://drupal.org/node/[nid]</em>, and <em>[nid].gdo</em> to link to <em>http://groups.drupal.org/node/[nid]</em> - Links will only be generated for valid node IDs using this format.');
 }
 
 function _dopl_filter($text) {
@@ -43,6 +50,10 @@ function _dopl_filter($text) {
   $pattern = '/(\b)([a-z0-9#\-]*)(\.(do))(\b)(\|"([^"]*)")?/';
   $text = preg_replace_callback($pattern, 'dopl_get_link', $text);
 
+  // Link drupal.org issue nodes by nid
+  $pattern = '/(\b)([a-z0-9#\-]*)(\.(issue))(\b)(\|"([^"]*)")?/';
+  $text = preg_replace_callback($pattern, 'dopl_get_issue', $text);
+
   // Link groups.drupal.org nodes by nid
   $pattern = '/(\b)([a-z0-9#\-]*)(\.(gdo))(\b)(\|"([^"]*)")?/';
   $text = preg_replace_callback($pattern, 'dopl_get_link', $text);
@@ -92,7 +103,6 @@ function dopl_get_link($matches = array()) {
   return $matches[0];
 }
 
-
 /**
  * @param string a valid url
  * 
@@ -110,4 +120,110 @@ function dopl_get_page_title($url) {
   else {
     return FALSE;
   }
-}
\ No newline at end of file
+}
+
+/**
+ * 
+ */
+function dopl_get_issue($matches = array()) {
+  $nid = $matches[2];
+  $url = 'http://drupal.org/node/' . $nid;
+  $link = '';
+  // using a different cache identifier in case the nid gets used in a do link as well
+  if ($data = cache_get('dopli:' . $matches[2])) {
+    $link = (array_key_exists(7, $matches)) ? l($url, $matches[7]) : $data->data;
+  }
+  else {
+    $data = @file_get_contents($url);
+    if ( FALSE === $data ) {
+      return FALSE;
+      dpm('boom!');
+    }
+    elseif (preg_match("#<title>(.+)<\/title>#iU", $data, $t)) {
+      //if url returns a issue page, we assume a issue / node exists
+      $page_title = substr(trim($t[1]), 0, -13);
+
+      // See if the issue is assigned to anyone.  If so, we'll include it either
+      // in the title attribute on hover
+      // Looking for <td>Assigned:</td><td>[Unassigned or username]</td>
+      if (preg_match("#<td>Assigned:</td><td>(.+)<\/td>#isU", $data, $t)) {
+        $username = trim($t[1]);
+      }
+      if ($username == 'Unassigned') {
+        $username = '';
+      }
+
+      // Grab the issue status.
+      // Looking for <td>Status:</td><td>[status]</td>
+      if (preg_match("#<td>Status:</td><td>(.+)<\/td>#isU", $data, $t)) {
+        $status = trim($t[1]);
+        switch ($status) {
+        case "active":
+          $sid = 1;
+          break;
+        case "needs work":
+          $sid = 13;
+          break;
+        case "needs review":
+          $sid = 18;
+          break;
+        case "reviewed &amp; tested by the community":
+          $sid = 14;
+          break;
+        case "patch (to be ported)":
+          $sid = 15;
+          break;
+        case "fixed":
+          $sid = 2;
+          break;
+        case "postponed":
+          $sid = 4;
+          break;
+        case "postponed (maintainer needs more info)":
+          $sid = 16;
+          break;
+        case "closed (duplicate)":
+          $sid = 3;
+          break;
+        case "closed (won't fix)" :
+          $sid = 5;
+          break;
+        case "closed (works as designed)":
+          $sid = 6;
+          break;
+        case "closed (cannot reproduce)":
+          $sid = 18;
+          break;
+        case "closed (fixed)":
+          $sid = 7;
+          break;
+        }
+      }
+
+      if (!empty($username)) {
+        // We have an assigned user, but we're not going to print it next to the
+        // issue link, so include it in title. l() runs $attributes through
+        // drupal_attributes() which escapes the value.
+        $attributes = array('title' => t('Status: !status, Assigned to: !username', array('!status' => $status, '!username' => $username)));
+      }
+      else {
+        // Just the status.
+        $attributes = array('title' => t('Status: !status', array('!status' => $status)));
+      }
+
+      $title = "#$nid: $page_title";
+      $issue_url = l($title, $url, array('attributes' => $attributes));
+      $issue_link = '<span class="project-issue-status-'. $sid .' project-issue-status-info">'. $issue_url;
+      if (!empty($username)) {
+        $issue_link .= ' <span class="project-issue-assigned-user">'. t('Assigned to: @username', array('@username' => $username)) .'</span>';
+      }
+      $issue_link .= '</span>';
+      cache_set('dopli:' . $matches[2], $issue_link);
+      $link = (array_key_exists(7, $matches)) ? $matches[7] : $issue_link;
+    }
+  }
+  if ($link) {
+    return $link;
+  }
+  return $matches[0];
+}
